From 4ab7f8f757f6874e4a48b572756f0020b764cf5a Mon Sep 17 00:00:00 2001 From: Jim Hague Date: Mon, 28 Oct 2019 17:11:00 +0000 Subject: [PATCH] Shared libraries - move versioning and export list into functions. Also for Windows add looking for a template .RC of the target name and adding that to the build too. --- CMakeLists.txt | 46 ++++--------------- cmake/include/getdns_shared_version.rc.in | 19 ++++++++ .../modules/TargetSharedLibraryExports.cmake | 27 +++++++++++ .../modules/TargetSharedLibraryVersion.cmake | 25 ++++++++++ 4 files changed, 80 insertions(+), 37 deletions(-) create mode 100644 cmake/include/getdns_shared_version.rc.in create mode 100644 cmake/modules/TargetSharedLibraryExports.cmake create mode 100644 cmake/modules/TargetSharedLibraryVersion.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index ca396734..51d78a10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,9 @@ include(CTest) include(GNUInstallDirs) include(TestBigEndian) +include(TargetSharedLibraryExports) +include(TargetSharedLibraryVersion) + # Target Platform if (WIN32 OR MINGW OR MSYS OR CYGWIN) set(HOSTOS "windows") @@ -582,50 +585,19 @@ if (ENABLE_SHARED) target_link_libraries(getdns_shared PUBLIC Libidn2::Libidn2) endif () set_target_properties(getdns_shared PROPERTIES OUTPUT_NAME getdns) - - if (NOT ENABLE_STATIC) - add_library(getdns ALIAS getdns_shared) - endif () + target_shared_library_version(getdns_shared ${GETDNS_VERSION_CURRENT} ${GETDNS_VERSION_REVISION} ${GETDNS_VERSION_AGE}) # Generate platform-specific link file with the export symbols. file(STRINGS src/libgetdns.symbols symbols) - if (WIN32) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/getdns.def" "LIBRARY GETDNS\n VERSION ${GETDNS_VERSION_CURRENT}.${GETDNS_VERSION_REVISION}\n EXPORTS\n") - foreach (symbol IN LISTS symbols) - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/getdns.def" " ${symbol}\n") - endforeach () - target_sources(getdns_shared PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/getdns.def") - elseif (APPLE) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/getdns.syms" "") - foreach (symbol IN LISTS symbols) - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/getdns.syms" "_${symbol}\n") - endforeach () - target_sources(getdns_shared PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/getdns.syms") - target_link_libraries(getdns_shared PRIVATE "-exported_symbols_list getdns.syms") + target_shared_library_exports(getdns_shared getdns "${symbols}") - # Follow libtool. Add one to major version, as version 0 doesn't work. - # But tag dynlib name with current-age. - math(EXPR major_version "${GETDNS_VERSION_CURRENT}+1") - math(EXPR dynlib_version "${GETDNS_VERSION_CURRENT}-${GETDNS_VERSION_AGE}") - set_target_properties(getdns_shared PROPERTIES VERSION "${dynlib_version}") - target_link_libraries(getdns_shared PRIVATE "-compatibility_version ${major_version}") - target_link_libraries(getdns_shared PRIVATE "-current_version ${major_version}.${GETDNS_VERSION_REVISION}") - else () - # Assume GNU ld. - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/getdns.ver" "{ global:\n") - foreach (symbol IN LISTS symbols) - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/getdns.ver" " ${symbol};\n") - endforeach () - file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/getdns.ver" "local:\n *;\n};\n") - target_link_libraries(getdns_shared PRIVATE "-Wl,--version-script=getdns.ver") - - # Again, follow libtool. Major version is current-age. - math(EXPR compat_version "${GETDNS_VERSION_CURRENT}-${GETDNS_VERSION_AGE}") - set_target_properties(getdns_shared PROPERTIES VERSION "${compat_version}.${GETDNS_VERSION_AGE}.${GETDNS_VERSION_REVISION}" SOVERSION "${compat_version}") + # If we're not building a static library, use this wherever we use + # the static library in tool and test builds. + if (NOT ENABLE_STATIC) + add_library(getdns ALIAS getdns_shared) endif () endif () - # The tools. if (BUILD_GETDNS_QUERY) add_executable(getdns_query src/tools/getdns_query.c) diff --git a/cmake/include/getdns_shared_version.rc.in b/cmake/include/getdns_shared_version.rc.in new file mode 100644 index 00000000..d69a36d6 --- /dev/null +++ b/cmake/include/getdns_shared_version.rc.in @@ -0,0 +1,19 @@ +1 VERSIONINFO + FILEVERSION @version_current@,@version_revision@,@version_age@,0 + PRODUCTVERSION @version_current@,@version_revision@,0,0 + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "getdns project\0" + VALUE "ProductName", "getdns\0" + VALUE "FileVersion", "@version_current@.@version_revision@\0" + VALUE "ProductVersion", "@version_current@.@version_revision@\0" + VALUE "LegalCopyright", "NLnet Labs, Sinodun, No Mountain Software. New BSD licence.\0" + END + END +END diff --git a/cmake/modules/TargetSharedLibraryExports.cmake b/cmake/modules/TargetSharedLibraryExports.cmake new file mode 100644 index 00000000..ab3f960e --- /dev/null +++ b/cmake/modules/TargetSharedLibraryExports.cmake @@ -0,0 +1,27 @@ +# Export only named entry points from shared library. +function(target_shared_library_exports lib libname symbols) + if (WIN32) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${libname}.def" "LIBRARY ${libname}\n EXPORTS\n") + foreach (symbol IN LISTS symbols) + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.def" " ${symbol}\n") + endforeach () + target_sources(${lib} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${libname}.def") + elseif (APPLE) + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${libname}.syms" "") + foreach (symbol IN LISTS symbols) + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.syms" "_${symbol}\n") + endforeach () + target_sources(${lib} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${libname}.syms") + target_link_libraries(${lib} PRIVATE "-exported_symbols_list ${libname}.syms") + elseif (UNIX) + # Assume GNU ld. + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${libname}.ver" "{ global:\n") + foreach (symbol IN LISTS symbols) + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.ver" " ${symbol};\n") + endforeach () + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/${libname}.ver" "local:\n *;\n};\n") + target_link_libraries(${lib} PRIVATE "-Wl,--version-script=getdns.ver") + else () + message(WARNING "Unknown platform, ${lib} exports not set.") + endif () +endfunction () diff --git a/cmake/modules/TargetSharedLibraryVersion.cmake b/cmake/modules/TargetSharedLibraryVersion.cmake new file mode 100644 index 00000000..368ade8c --- /dev/null +++ b/cmake/modules/TargetSharedLibraryVersion.cmake @@ -0,0 +1,25 @@ +# Add version to given shared library linkage. +function(target_shared_library_version lib version_current version_revision version_age) + if (WIN32) + set(rc_template "${CMAKE_CURRENT_SOURCE_DIR}/cmake/include/${lib}_version.rc.in") + if (EXISTS ${rc_template}) + configure_file(${rc_template} ${lib}.rc @ONLY) + target_sources(${lib} PRIVATE ${lib}.rc) + endif () + target_link_libraries(${lib} PRIVATE "-VERSION:${version_current}.${version_revision}") + elseif (APPLE) + # Follow libtool. Add one to major version, as version 0 doesn't work. + # But tag dynlib name with current-age. + math(EXPR major_version "${version_current}+1") + math(EXPR dynlib_version "${version_current}-${version_age}") + set_target_properties(${lib} PROPERTIES VERSION "${dynlib_version}") + target_link_libraries(${lib} PRIVATE "-compatibility_version ${major_version}") + target_link_libraries(${lib} PRIVATE "-current_version ${major_version}.${version_revision}") + elseif (UNIX) + # Assume GNU ld, and again follow libtool. Major version is current-age. + math(EXPR compat_version "${version_current}-${version_age}") + set_target_properties(${lib} PROPERTIES VERSION "${compat_version}.${version_age}.${version_revision}" SOVERSION "${compat_version}") + else () + message(WARNING "Unknown platform, ${lib} will not be versioned.") + endif () +endfunction ()