From: Viktor Szakats Date: Sun, 30 Jul 2023 12:14:23 +0000 (+0000) Subject: cmake: add support for single libcurl compilation pass X-Git-Tag: curl-8_3_0~255 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ebc74c36a19a1700af394c16855ce144d9878e3;p=thirdparty%2Fcurl.git cmake: add support for single libcurl compilation pass Before this patch CMake builds used two separate compilation passes to build the shared and static libcurl respectively. This patch allows to reduce that to a single pass if the target platform and build settings allow it. This reduces CMake build times when building both static and shared libcurl at the same time, making these dual builds an almost zero-cost option. Enable this feature for Windows builds, where the difference between the two passes was the use of `__declspec(dllexport)` attribute for exported API functions for the shared builds. This patch replaces this method with the use of `libcurl.def` at DLL link time. Also update `Makefile.mk` to use `libcurl.def` to export libcurl API symbols on Windows. This simplifies (or fixes) this build method (e.g. in curl-for-win, which generated a `libcurl.def` from `.h` files using an elaborate set of transformations). `libcurl.def` has the maintenance cost of keeping the list of public libcurl API symbols up-to-date. This list seldom changes, so the cost is low. Closes #11546 --- diff --git a/.reuse/dep5 b/.reuse/dep5 index 0766738044..cdefb1698f 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -23,6 +23,10 @@ Files: projects/Windows/* Copyright: Daniel Stenberg, , et al. License: curl +Files: libcurl.def +Copyright: Daniel Stenberg, , et al. +License: curl + # Single files we do not want to edit directly Files: CHANGES Copyright: Daniel Stenberg, , et al. diff --git a/Makefile.am b/Makefile.am index fa20363bdf..6c780a849d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -148,7 +148,8 @@ PLAN9_DIST = plan9/include/mkfile \ EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \ RELEASE-NOTES buildconf libcurl.pc.in MacOSX-Framework $(CMAKE_DIST) \ - $(VC_DIST) $(WINBUILD_DIST) $(PLAN9_DIST) lib/libcurl.vers.in buildconf.bat + $(VC_DIST) $(WINBUILD_DIST) $(PLAN9_DIST) lib/libcurl.vers.in buildconf.bat \ + libcurl.def CLEANFILES = $(VC10_LIBVCXPROJ) $(VC10_SRCVCXPROJ) $(VC11_LIBVCXPROJ) \ $(VC11_SRCVCXPROJ) $(VC12_LIBVCXPROJ) $(VC12_SRCVCXPROJ) $(VC14_LIBVCXPROJ) \ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 0239f805be..faae6452c5 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -108,10 +108,46 @@ if(WIN32 AND set(IMPORT_LIB_SUFFIX "_imp") endif() +# On supported platforms, do a single compilation pass for libcurl sources +# and reuse these objects to generate both static and shared target. +# This is possible where PIC is the default for both shared and static and +# there is a way to tell the linker which libcurl symbols it should export +# (vs. marking these symbols exportable at compile-time). +if(WIN32 AND NOT DEFINED SHARE_LIB_OBJECT) + set(SHARE_LIB_OBJECT ON) +endif() + +if(SHARE_LIB_OBJECT) + set(LIB_OBJECT "libcurl_object") + add_library(${LIB_OBJECT} OBJECT ${HHEADERS} ${CSOURCES}) + target_link_libraries(${LIB_OBJECT} PRIVATE ${CURL_LIBS}) + set_target_properties(${LIB_OBJECT} PROPERTIES + COMPILE_DEFINITIONS "BUILDING_LIBCURL" + INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB") + if(HIDES_CURL_PRIVATE_SYMBOLS) + set_target_properties(${LIB_OBJECT} PROPERTIES + COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS" + COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}") + endif() + if(CURL_HAS_LTO) + set_target_properties(${LIB_OBJECT} PROPERTIES + INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE + INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE) + endif() + + target_include_directories(${LIB_OBJECT} INTERFACE + $ + $) + + set(LIB_SOURCE $) +else() + set(LIB_SOURCE ${HHEADERS} ${CSOURCES}) +endif() + # we want it to be called libcurl on all platforms if(BUILD_STATIC_LIBS) list(APPEND libcurl_export ${LIB_STATIC}) - add_library(${LIB_STATIC} STATIC ${HHEADERS} ${CSOURCES}) + add_library(${LIB_STATIC} STATIC ${LIB_SOURCE}) add_library(${PROJECT_NAME}::${LIB_STATIC} ALIAS ${LIB_STATIC}) target_link_libraries(${LIB_STATIC} PRIVATE ${CURL_LIBS}) # Remove the "lib" prefix since the library is already named "libcurl". @@ -142,10 +178,10 @@ endif() if(BUILD_SHARED_LIBS) list(APPEND libcurl_export ${LIB_SHARED}) - add_library(${LIB_SHARED} SHARED ${HHEADERS} ${CSOURCES}) + add_library(${LIB_SHARED} SHARED ${LIB_SOURCE}) add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED}) if(WIN32) - set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc) + set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc ${CURL_SOURCE_DIR}/libcurl.def) endif() target_link_libraries(${LIB_SHARED} PRIVATE ${CURL_LIBS}) # Remove the "lib" prefix since the library is already named "libcurl". diff --git a/lib/Makefile.mk b/lib/Makefile.mk index b298ac0707..e1f782bac8 100644 --- a/lib/Makefile.mk +++ b/lib/Makefile.mk @@ -388,6 +388,7 @@ ifdef WIN32 CURL_DLL_SUFFIX ?= libcurl_dll_LIBRARY := libcurl$(CURL_DLL_SUFFIX).dll libcurl_dll_a_LIBRARY := libcurl.dll.a +CURL_LDFLAGS_LIB += $(PROOT)/libcurl.def ifdef MAP libcurl_map_LIBRARY := libcurl$(CURL_DLL_SUFFIX).map CURL_LDFLAGS_LIB += -Wl,-Map,$(libcurl_map_LIBRARY) diff --git a/libcurl.def b/libcurl.def new file mode 100644 index 0000000000..e84d4c6558 --- /dev/null +++ b/libcurl.def @@ -0,0 +1,92 @@ +EXPORTS +curl_easy_cleanup +curl_easy_duphandle +curl_easy_escape +curl_easy_getinfo +curl_easy_header +curl_easy_init +curl_easy_nextheader +curl_easy_option_by_id +curl_easy_option_by_name +curl_easy_option_next +curl_easy_pause +curl_easy_perform +curl_easy_recv +curl_easy_reset +curl_easy_send +curl_easy_setopt +curl_easy_strerror +curl_easy_unescape +curl_easy_upkeep +curl_escape +curl_formadd +curl_formfree +curl_formget +curl_free +curl_getdate +curl_getenv +curl_global_cleanup +curl_global_init +curl_global_init_mem +curl_global_sslset +curl_maprintf +curl_mfprintf +curl_mime_addpart +curl_mime_data +curl_mime_data_cb +curl_mime_encoder +curl_mime_filedata +curl_mime_filename +curl_mime_free +curl_mime_headers +curl_mime_init +curl_mime_name +curl_mime_subparts +curl_mime_type +curl_mprintf +curl_msnprintf +curl_msprintf +curl_multi_add_handle +curl_multi_assign +curl_multi_cleanup +curl_multi_fdset +curl_multi_info_read +curl_multi_init +curl_multi_perform +curl_multi_poll +curl_multi_remove_handle +curl_multi_setopt +curl_multi_socket +curl_multi_socket_action +curl_multi_socket_all +curl_multi_strerror +curl_multi_timeout +curl_multi_wait +curl_multi_wakeup +curl_mvaprintf +curl_mvfprintf +curl_mvprintf +curl_mvsnprintf +curl_mvsprintf +curl_pushheader_byname +curl_pushheader_bynum +curl_share_cleanup +curl_share_init +curl_share_setopt +curl_share_strerror +curl_slist_append +curl_slist_free_all +curl_strequal +curl_strnequal +curl_unescape +curl_url +curl_url_cleanup +curl_url_dup +curl_url_get +curl_url_set +curl_url_strerror +curl_version +curl_version_info +curl_ws_meta +curl_ws_recv +curl_ws_send