cmake: support building static and shared libcurl in one go

This patch adds the ability to build a static and shared libcurl library
in a single build session. It also adds an option to select which one to
use when building the curl executable.

New build options:
- `BUILD_STATIC_LIBS`. Default: `OFF`.
  Enabled automatically if `BUILD_SHARED_LIBS` is `OFF`.
- `BUILD_STATIC_CURL`. Default: `OFF`.
  Requires `BUILD_STATIC_LIBS` enabled.
  Enabled automatically if building static libcurl only.
- `STATIC_LIB_SUFFIX`. Default: empty.
- `IMPORT_LIB_SUFFIX`. Default: `_imp` if implib filename would collide
  with static lib name (typically with MSVC) in Windows builds.
  Otherwise empty.

Also:

- Stop setting the `CURL_STATICLIB` macro via `curl_config.h`, and pass
  it directly to the compiler. This also allows to delete a condition
  from `tests/server/CMakeLists.txt`.

- Complete a TODO by following the logic used in autotools (also for
  `LIBCURL_NO_SHARED`), and set `-DCURL_STATICLIB` in `Cflags:` of
  `libcurl.pc` for _static-only_ curl builds.

- Convert an existing CI test to build both shared and static libcurl.

Closes #11505
This commit is contained in:
Viktor Szakats 2023-06-22 09:24:37 +00:00
Родитель 40c63290e3
Коммит 1199308dbc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5ABD165E2AEF201
8 изменённых файлов: 143 добавлений и 90 удалений

2
.github/workflows/macos.yml поставляемый
Просмотреть файл

@ -180,7 +180,7 @@ jobs:
generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/libressl -DCURL_DISABLE_LDAP=ON -DCURL_DISABLE_LDAPS=ON -DCMAKE_UNITY_BUILD=ON
- name: libssh2
install: nghttp2 openssl libssh2
generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_USE_LIBSSH2=ON
generate: -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -DCURL_USE_LIBSSH2=ON -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=ON
steps:
- run: echo libtool autoconf automake pkg-config ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
name: 'brew bundle'

Просмотреть файл

@ -33,3 +33,6 @@ endif()
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@")
# Alias for either shared or static library
add_library(curl::libcurl ALIAS curl::@LIB_SELECTED@)

Просмотреть файл

@ -103,6 +103,8 @@ option(CURL_WERROR "Turn compiler warnings into errors" OFF)
option(PICKY_COMPILER "Enable picky compiler options" ON)
option(BUILD_CURL_EXE "Set to ON to build curl executable." ON)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(BUILD_STATIC_LIBS "Build shared libraries" OFF)
option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF)
option(ENABLE_ARES "Set to ON to enable c-ares support" OFF)
if(WIN32)
option(CURL_STATIC_CRT "Set to ON to build libcurl with static CRT on Windows (/MT)." OFF)
@ -146,6 +148,32 @@ if(NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "-d")
endif()
set(LIB_STATIC "libcurl_static")
set(LIB_SHARED "libcurl_shared")
if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
set(BUILD_STATIC_LIBS ON)
endif()
if(NOT BUILD_STATIC_CURL AND NOT BUILD_SHARED_LIBS)
set(BUILD_STATIC_CURL ON)
elseif(BUILD_STATIC_CURL AND NOT BUILD_STATIC_LIBS)
set(BUILD_STATIC_CURL OFF)
endif()
# lib flavour selected for curl tool
if(BUILD_STATIC_CURL)
set(LIB_SELECTED_FOR_EXE ${LIB_STATIC})
else()
set(LIB_SELECTED_FOR_EXE ${LIB_SHARED})
endif()
# lib flavour selected for example and test programs.
if(BUILD_SHARED_LIBS)
set(LIB_SELECTED ${LIB_SHARED})
else()
set(LIB_SELECTED ${LIB_STATIC})
endif()
# initialize CURL_LIBS
set(CURL_LIBS "")
@ -1539,8 +1567,6 @@ message(STATUS "Enabled SSL backends: ${SSL_BACKENDS}")
set(CC "${CMAKE_C_COMPILER}")
# TODO probably put a -D... options here?
set(CONFIGURE_OPTIONS "")
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
set(CPPFLAG_CURL_STATICLIB "")
set(CURLVERSION "${CURL_VERSION}")
set(exec_prefix "\${prefix}")
set(includedir "\${prefix}/include")
@ -1570,12 +1596,17 @@ foreach(_lib ${CMAKE_C_IMPLICIT_LINK_LIBRARIES} ${CURL_LIBS})
endforeach()
if(BUILD_SHARED_LIBS)
set(ENABLE_SHARED "yes")
set(ENABLE_STATIC "no")
set(LIBCURL_NO_SHARED "")
set(CPPFLAG_CURL_STATICLIB "")
else()
set(ENABLE_SHARED "no")
set(ENABLE_STATIC "yes")
set(LIBCURL_NO_SHARED "${LIBCURL_LIBS}")
set(CPPFLAG_CURL_STATICLIB "-DCURL_STATICLIB")
endif()
if(BUILD_STATIC_LIBS)
set(ENABLE_STATIC "yes")
else()
set(ENABLE_STATIC "no")
endif()
# "a" (Linux) or "lib" (Windows)
string(REPLACE "." "" libext "${CMAKE_STATIC_LIBRARY_SUFFIX}")

Просмотреть файл

@ -25,14 +25,6 @@ set(LIB_NAME libcurl)
set(LIBCURL_OUTPUT_NAME libcurl CACHE STRING "Basename of the curl library")
add_definitions(-DBUILDING_LIBCURL)
if(BUILD_SHARED_LIBS)
set(CURL_STATICLIB NO)
else()
set(CURL_STATICLIB YES)
endif()
# Use:
# * CURL_STATICLIB
configure_file(curl_config.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h)
@ -43,10 +35,6 @@ list(APPEND HHEADERS
${CMAKE_CURRENT_BINARY_DIR}/curl_config.h
)
if(WIN32 AND NOT CURL_STATICLIB)
list(APPEND CSOURCES libcurl.rc)
endif()
# The rest of the build
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../include)
@ -59,11 +47,6 @@ if(USE_ARES)
include_directories(${CARES_INCLUDE_DIR})
endif()
add_library(
${LIB_NAME}
${HHEADERS} ${CSOURCES}
)
add_library(
curlu # special libcurlu library just for unittests
STATIC
@ -72,32 +55,16 @@ add_library(
)
target_compile_definitions(curlu PUBLIC UNITTESTS CURL_STATICLIB)
add_library(
${PROJECT_NAME}::${LIB_NAME}
ALIAS ${LIB_NAME}
)
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()
if(NOT BUILD_SHARED_LIBS)
set_target_properties(${LIB_NAME} PROPERTIES INTERFACE_COMPILE_DEFINITIONS CURL_STATICLIB)
endif()
target_link_libraries(${LIB_NAME} PRIVATE ${CURL_LIBS})
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)
set_target_properties(${LIB_NAME} PROPERTIES
COMPILE_DEFINITIONS BUILDING_LIBCURL
OUTPUT_NAME ${LIBCURL_OUTPUT_NAME}
)
if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
CMAKE_SYSTEM_NAME STREQUAL "Linux" OR
CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
@ -114,39 +81,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
math(EXPR CMAKESONAME "${VERSIONCHANGE} - ${VERSIONDEL}")
set(CMAKEVERSION "${CMAKESONAME}.${VERSIONDEL}.${VERSIONADD}")
set_target_properties(${LIB_NAME} PROPERTIES
VERSION ${CMAKEVERSION}
SOVERSION ${CMAKESONAME}
)
else()
unset(CMAKESONAME)
endif()
if(HIDES_CURL_PRIVATE_SYMBOLS)
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS")
set_property(TARGET ${LIB_NAME} APPEND PROPERTY COMPILE_FLAGS ${CURL_CFLAG_SYMBOLS_HIDE})
endif()
# Remove the "lib" prefix since the library is already named "libcurl".
set_target_properties(${LIB_NAME} PROPERTIES PREFIX "")
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_PREFIX "")
if(CURL_HAS_LTO)
set_target_properties(${LIB_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE)
endif()
if(WIN32)
if(BUILD_SHARED_LIBS)
if(MSVC)
# Add "_imp" as a suffix before the extension to avoid conflicting with
# the statically linked "libcurl.lib"
set_target_properties(${LIB_NAME} PROPERTIES IMPORT_SUFFIX "_imp.lib")
endif()
endif()
elseif(NOT CMAKE_CROSSCOMPILING)
if(NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
# on not-Windows and not-crosscompiling, check for writable argv[]
include(CheckCSourceRuns)
check_c_source_runs("
@ -159,19 +98,104 @@ int main(int argc, char **argv)
HAVE_WRITABLE_ARGV)
endif()
target_include_directories(${LIB_NAME} INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CURL_SOURCE_DIR}/include>)
## 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()
# 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(${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 ${HHEADERS} ${CSOURCES})
add_library(${PROJECT_NAME}::${LIB_SHARED} ALIAS ${LIB_SHARED})
if(WIN32)
set_property(TARGET ${LIB_SHARED} APPEND PROPERTY SOURCES libcurl.rc)
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)
install(TARGETS ${LIB_NAME}
EXPORT ${TARGETS_EXPORT_NAME}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
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 ${LIB_NAME}
export(TARGETS ${libcurl_export}
FILE ${PROJECT_BINARY_DIR}/libcurl-target.cmake
NAMESPACE ${PROJECT_NAME}::
)

Просмотреть файл

@ -132,9 +132,6 @@
/* Use Windows LDAP implementation */
#cmakedefine USE_WIN32_LDAP 1
/* when not building a shared library */
#cmakedefine CURL_STATICLIB 1
/* your Entropy Gathering Daemon socket pathname */
#cmakedefine EGD_SOCKET ${EGD_SOCKET}

Просмотреть файл

@ -62,7 +62,7 @@ if(WIN32)
endif()
# CURL_CFILES, CURLX_CFILES, CURL_HFILES come from Makefile.inc
if(NOT BUILD_SHARED_LIBS)
if(BUILD_STATIC_CURL)
set(CURLX_CFILES ../lib/dynbuf.c)
endif()
@ -107,7 +107,7 @@ include_directories(
)
#Build curl executable
target_link_libraries(${EXE_NAME} libcurl ${CURL_LIBS})
target_link_libraries(${EXE_NAME} ${LIB_SELECTED_FOR_EXE} ${CURL_LIBS})
################################################################################

Просмотреть файл

@ -25,7 +25,7 @@ set(TARGET_LABEL_PREFIX "Test ")
function(setup_test TEST_NAME) # ARGN are the files in the test
if(NOT BUILD_SHARED_LIBS)
if(LIB_SELECTED STREQUAL LIB_STATIC)
# These are part of the libcurl static lib. Do not compile/link them again.
list(REMOVE_ITEM ARGN ${WARNLESS} ${MULTIBYTE} ${TIMEDIFF})
endif()
@ -44,7 +44,7 @@ function(setup_test TEST_NAME) # ARGN are the files in the test
include_directories(${CARES_INCLUDE_DIR})
endif()
target_link_libraries(${TEST_NAME} libcurl ${CURL_LIBS})
target_link_libraries(${TEST_NAME} ${LIB_SELECTED} ${CURL_LIBS})
set_target_properties(${TEST_NAME}
PROPERTIES COMPILE_DEFINITIONS ${UPPER_TEST_NAME})

Просмотреть файл

@ -50,10 +50,8 @@ function(SETUP_EXECUTABLE TEST_NAME) # ARGN are the files in the test
# to build the servers. In order to achieve proper linkage of these
# files on Win32 targets it is necessary to build the test servers
# with CURL_STATICLIB defined, independently of how libcurl is built.
if(BUILD_SHARED_LIBS)
set_target_properties(${TEST_NAME} PROPERTIES
COMPILE_DEFINITIONS CURL_STATICLIB) # ${UPPER_TEST_NAME}
endif()
set_target_properties(${TEST_NAME} PROPERTIES
COMPILE_DEFINITIONS CURL_STATICLIB) # ${UPPER_TEST_NAME}
set_target_properties(${TEST_NAME} PROPERTIES
PROJECT_LABEL "${TARGET_LABEL_PREFIX}${TEST_NAME}")
endfunction()