]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
cmake: add support for single libcurl compilation pass
authorViktor Szakats <commit@vsz.me>
Sun, 30 Jul 2023 12:14:23 +0000 (12:14 +0000)
committerViktor Szakats <commit@vsz.me>
Tue, 1 Aug 2023 08:12:26 +0000 (08:12 +0000)
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

.reuse/dep5
Makefile.am
lib/CMakeLists.txt
lib/Makefile.mk
libcurl.def [new file with mode: 0644]

index 0766738044b03591fc328f852bdfa5ee4152375e..cdefb1698f06676321fdd280ba3b2d8e66fc2585 100644 (file)
@@ -23,6 +23,10 @@ Files: projects/Windows/*
 Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
 License: curl
 
+Files: libcurl.def
+Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
+License: curl
+
 # Single files we do not want to edit directly
 Files: CHANGES
 Copyright: Daniel Stenberg, <daniel@haxx.se>, et al.
index fa20363bdf9e503fbf9a215042fab234344e8ea7..6c780a849de2d2509afcaab5b9a6ad56d26ebf30 100644 (file)
@@ -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) \
index 0239f805be728f10334897c7fb0927accba64170..faae6452c5ddbdb8850205424a7836de77312015 100644 (file)
@@ -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
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+    $<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
+
+  set(LIB_SOURCE $<TARGET_OBJECTS:${LIB_OBJECT}>)
+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".
index b298ac070733dfe8eccc69e6f879a683263a6847..e1f782bac8f331fd8943ede9b517009bf6a82bb7 100644 (file)
@@ -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 (file)
index 0000000..e84d4c6
--- /dev/null
@@ -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