mirror of
https://github.com/curl/curl.git
synced 2025-01-12 13:55:11 +08:00
2ebc74c36a
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
239 lines
8.5 KiB
CMake
239 lines
8.5 KiB
CMake
#***************************************************************************
|
|
# _ _ ____ _
|
|
# Project ___| | | | _ \| |
|
|
# / __| | | | |_) | |
|
|
# | (__| |_| | _ <| |___
|
|
# \___|\___/|_| \_\_____|
|
|
#
|
|
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
#
|
|
# This software is licensed as described in the file COPYING, which
|
|
# you should have received as part of this distribution. The terms
|
|
# are also available at https://curl.se/docs/copyright.html.
|
|
#
|
|
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
# copies of the Software, and permit persons to whom the Software is
|
|
# furnished to do so, under the terms of the COPYING file.
|
|
#
|
|
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
# KIND, either express or implied.
|
|
#
|
|
# SPDX-License-Identifier: curl
|
|
#
|
|
###########################################################################
|
|
set(LIB_NAME libcurl)
|
|
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
|
|
add_definitions(-DBUILDING_LIBCURL)
|
|
|
|
configure_file(curl_config.h.cmake
|
|
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
|
|
|
|
transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake")
|
|
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake)
|
|
|
|
list(APPEND HHEADERS
|
|
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
|
|
)
|
|
|
|
# The rest of the build
|
|
|
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
|
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
|
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/..)
|
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|
if(USE_ARES)
|
|
include_directories(${CARES_INCLUDE_DIR})
|
|
endif()
|
|
|
|
add_library(
|
|
curlu # special libcurlu library just for unittests
|
|
STATIC
|
|
EXCLUDE_FROM_ALL
|
|
${HHEADERS} ${CSOURCES}
|
|
)
|
|
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
|
|
|
|
if(ENABLE_CURLDEBUG)
|
|
# We must compile memdebug.c separately to avoid memdebug.h redefinitions
|
|
# being applied to memdebug.c itself.
|
|
set_source_files_properties(memdebug.c PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
|
|
endif()
|
|
target_link_libraries(curlu PRIVATE ${CURL_LIBS})
|
|
|
|
transform_makefile_inc("Makefile.soname" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake")
|
|
include(${CMAKE_CURRENT_BINARY_DIR}/Makefile.soname.cmake)
|
|
|
|
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
|
|
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
|
|
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
|
|
CMAKE_SYSTEM_NAME STREQUAL "SunOS" OR
|
|
CMAKE_SYSTEM_NAME STREQUAL "GNU/kFreeBSD" OR
|
|
|
|
# FreeBSD comes with the a.out and elf flavours
|
|
# but a.out was supported up to version 3.x and
|
|
# elf from 3.x. I cannot imagine someone running
|
|
# CMake on those ancient systems
|
|
CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
|
|
|
|
CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
|
|
|
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
|
|
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
|
|
else()
|
|
unset(CMAKESONAME)
|
|
endif()
|
|
|
|
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
|
|
# on not-Windows and not-crosscompiling, check for writable argv[]
|
|
include(CheckCSourceRuns)
|
|
check_c_source_runs("
|
|
int main(int argc, char **argv)
|
|
{
|
|
(void)argc;
|
|
argv[0][0] = ' ';
|
|
return (argv[0][0] == ' ')?0:1;
|
|
}"
|
|
HAVE_WRITABLE_ARGV)
|
|
endif()
|
|
|
|
## Library definition
|
|
|
|
# Add "_imp" as a suffix before the extension to avoid conflicting with
|
|
# the statically linked "libcurl.lib" (typically with MSVC)
|
|
if(WIN32 AND
|
|
NOT IMPORT_LIB_SUFFIX AND
|
|
CMAKE_STATIC_LIBRARY_SUFFIX STREQUAL CMAKE_IMPORT_LIBRARY_SUFFIX)
|
|
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 ${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".
|
|
set_target_properties(${LIB_STATIC} PROPERTIES
|
|
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
|
SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
|
COMPILE_DEFINITIONS "BUILDING_LIBCURL"
|
|
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB")
|
|
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
|
set_target_properties(${LIB_STATIC} PROPERTIES
|
|
COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
|
|
COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
|
endif()
|
|
if(CURL_HAS_LTO)
|
|
set_target_properties(${LIB_STATIC} PROPERTIES
|
|
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
|
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
|
endif()
|
|
if(CMAKEVERSION AND CMAKESONAME)
|
|
set_target_properties(${LIB_STATIC} PROPERTIES
|
|
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
|
|
endif()
|
|
|
|
target_include_directories(${LIB_STATIC} INTERFACE
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
|
endif()
|
|
|
|
if(BUILD_SHARED_LIBS)
|
|
list(APPEND libcurl_export ${LIB_SHARED})
|
|
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 ${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".
|
|
set_target_properties(${LIB_SHARED} PROPERTIES
|
|
PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}"
|
|
IMPORT_PREFIX "" IMPORT_SUFFIX "${IMPORT_LIB_SUFFIX}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
|
|
COMPILE_DEFINITIONS "BUILDING_LIBCURL"
|
|
POSITION_INDEPENDENT_CODE ON)
|
|
if(HIDES_CURL_PRIVATE_SYMBOLS)
|
|
set_target_properties(${LIB_SHARED} PROPERTIES
|
|
COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS"
|
|
COMPILE_FLAGS "${CURL_CFLAG_SYMBOLS_HIDE}")
|
|
endif()
|
|
if(CURL_HAS_LTO)
|
|
set_target_properties(${LIB_SHARED} PROPERTIES
|
|
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
|
|
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
|
|
endif()
|
|
if(CMAKEVERSION AND CMAKESONAME)
|
|
set_target_properties(${LIB_SHARED} PROPERTIES
|
|
VERSION ${CMAKEVERSION} SOVERSION ${CMAKESONAME})
|
|
endif()
|
|
|
|
target_include_directories(${LIB_SHARED} INTERFACE
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
|
|
endif()
|
|
|
|
add_library(${LIB_NAME} ALIAS ${LIB_SELECTED})
|
|
add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED})
|
|
|
|
if(CURL_ENABLE_EXPORT_TARGET)
|
|
if(BUILD_STATIC_LIBS)
|
|
install(TARGETS ${LIB_STATIC}
|
|
EXPORT ${TARGETS_EXPORT_NAME}
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
)
|
|
endif()
|
|
if(BUILD_SHARED_LIBS)
|
|
install(TARGETS ${LIB_SHARED}
|
|
EXPORT ${TARGETS_EXPORT_NAME}
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
)
|
|
endif()
|
|
|
|
export(TARGETS ${libcurl_export}
|
|
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
|
|
NAMESPACE ${PROJECT_NAME}::
|
|
)
|
|
endif()
|