Skip to content

Commit

Permalink
cmake: add support for single libcurl compilation pass
Browse files Browse the repository at this point in the history
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 curl#11546
  • Loading branch information
vszakats committed Aug 1, 2023
1 parent dee310d commit 2ebc74c
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .reuse/dep5
Expand Up @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion Makefile.am
Expand Up @@ -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) \
Expand Down
42 changes: 39 additions & 3 deletions lib/CMakeLists.txt
Expand Up @@ -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".
Expand Down Expand Up @@ -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".
Expand Down
1 change: 1 addition & 0 deletions lib/Makefile.mk
Expand Up @@ -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)
Expand Down
92 changes: 92 additions & 0 deletions 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

0 comments on commit 2ebc74c

Please sign in to comment.