Skip to content

Add CMAKE options to be able to build shared and static versions of the library at the same time #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Async++Config.cmake.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
include(CMakeFindDependencyMacro)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/Async++.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/asyncxx-targets.cmake")
179 changes: 131 additions & 48 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,21 @@
cmake_minimum_required(VERSION 3.1)
project(Async++ C CXX)

option(BUILD_SHARED_LIBS "Build Async++ as a shared library" ON)
option(ASYNCXX_BUILD_SHARED "Build shared library" ON)
option(ASYNCXX_BUILD_STATIC "Build static library" OFF)
option(USE_CXX_EXCEPTIONS "Enable C++ exception support" ON)
if (APPLE)
option(BUILD_FRAMEWORK "Build a Mac OS X framework instead of a library" OFF)
if (BUILD_FRAMEWORK AND NOT BUILD_SHARED_LIBS)
if (BUILD_FRAMEWORK AND NOT ASYNCXX_BUILD_SHARED)
message(FATAL_ERROR "Can't build a framework with static libraries")
endif()
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

set(ASYNCXX_SHARED_LIBRARY async++)
set(ASYNCXX_STATIC_LIBRARY async++-static)

# Add all source and header files so IDEs can see them
set(ASYNCXX_INCLUDE
${PROJECT_SOURCE_DIR}/include/async++/aligned_alloc.h
Expand Down Expand Up @@ -61,59 +65,124 @@ set(ASYNCXX_SRC
)
source_group(include FILES ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE})
source_group(src FILES ${ASYNCXX_SRC})
add_library(Async++ ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE} ${ASYNCXX_SRC})

# Async++ only depends on the C++11 standard libraries, but some implementations
# require the -pthread compiler flag to enable threading functionality.
if (NOT MSVC)
target_compile_options(Async++ PRIVATE -std=c++11)
if(${ASYNCXX_BUILD_SHARED})
list(APPEND ASYNCXX_TARGETS ${ASYNCXX_SHARED_LIBRARY})
endif()
if (APPLE)
# Use libc++ on Mac because the shipped libstdc++ version is ancient
target_compile_options(Async++ PRIVATE -stdlib=libc++)
set_target_properties(Async++ PROPERTIES LINK_FLAGS -stdlib=libc++)

if(${ASYNCXX_BUILD_STATIC})
list(APPEND ASYNCXX_TARGETS ${ASYNCXX_STATIC_LIBRARY})
endif()

if(NOT ASYNCXX_TARGETS)
message(FATAL_ERROR "No targets are specified")
endif()

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(Async++ PUBLIC Threads::Threads)

# Set up preprocessor definitions
target_include_directories(Async++ PRIVATE ${PROJECT_SOURCE_DIR}/include)
set_target_properties(Async++ PROPERTIES DEFINE_SYMBOL LIBASYNC_BUILD)
if (BUILD_SHARED_LIBS)
# Minimize the set of symbols exported by libraries
set_target_properties(Async++ PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
else()
target_compile_definitions(Async++ PUBLIC LIBASYNC_STATIC)
endif()
if(${ASYNCXX_BUILD_SHARED})
message(STATUS "Creating shared library: ${ASYNCXX_SHARED_LIBRARY}")
add_library(${ASYNCXX_SHARED_LIBRARY} SHARED ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE} ${ASYNCXX_SRC})
target_compile_features(${ASYNCXX_SHARED_LIBRARY} PUBLIC cxx_std_14)

# Async++ only depends on the C++11 standard libraries, but some implementations
# require the -pthread compiler flag to enable threading functionality.
if (NOT MSVC)
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PRIVATE -std=c++11)
endif()
if (APPLE)
# Use libc++ on Mac because the shipped libstdc++ version is ancient
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PRIVATE -stdlib=libc++)
set_target_properties(${ASYNCXX_SHARED_LIBRARY} PROPERTIES LINK_FLAGS -stdlib=libc++)
endif()
target_link_libraries(${ASYNCXX_SHARED_LIBRARY} PUBLIC Threads::Threads)
# Set up preprocessor definitions
target_include_directories(${ASYNCXX_SHARED_LIBRARY} PRIVATE ${PROJECT_SOURCE_DIR}/include)
set_target_properties(${ASYNCXX_SHARED_LIBRARY} PROPERTIES DEFINE_SYMBOL LIBASYNC_BUILD)
set_target_properties(${ASYNCXX_SHARED_LIBRARY} PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON)
# Enable warnings for strict C++ standard conformance
if (NOT MSVC)
target_compile_options(Async++ PRIVATE -Wall -Wextra -pedantic)
endif()

if (NOT MSVC)
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PRIVATE -Wall -Wextra -pedantic)
endif()
# Async++ doesn't make use of RTTI information, so don't generate it.
# There are issues on Apple platforms with exceptions and -fno-rtti, so keep it
# enabled there.
# See https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti
if (MSVC)
target_compile_options(Async++ PRIVATE /GR-)
elseif(NOT APPLE)
target_compile_options(Async++ PRIVATE -fno-rtti)
endif()

# Allow disabling exceptions, but warn the user about the consequences
if (NOT USE_CXX_EXCEPTIONS)
message(WARNING "Exceptions have been disabled. Any operation that would "
"throw an exception will result in a call to std::abort() instead.")
target_compile_definitions(Async++ PUBLIC LIBASYNC_NO_EXCEPTIONS)
if (MSVC)
target_compile_options(Async++ PUBLIC /EHs-c-)
else()
target_compile_options(Async++ PUBLIC -fno-exceptions)
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PRIVATE /GR-)
elseif(NOT APPLE)
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PRIVATE -fno-rtti)
endif()
# Allow disabling exceptions, but warn the user about the consequences
if (NOT USE_CXX_EXCEPTIONS)
message(WARNING "Exceptions have been disabled. Any operation that would "
"throw an exception will result in a call to std::abort() instead.")
target_compile_definitions(${ASYNCXX_SHARED_LIBRARY} PUBLIC LIBASYNC_NO_EXCEPTIONS)
if (MSVC)
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PUBLIC /EHs-c-)
else()
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PUBLIC -fno-exceptions)
endif()
endif()
# /Zc:__cplusplus is required to make __cplusplus accurate
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
# (according to https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
# That version is equivalent to _MSC_VER==1914
# (according to https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2019)
# CMake's ${MSVC_VERSION} is equivalent to _MSC_VER
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
# GREATER and EQUAL are used because GREATER_EQUAL is available starting with CMake 3.7
# (according to https://cmake.org/cmake/help/v3.7/release/3.7.html#commands)
if ((MSVC) AND ((MSVC_VERSION GREATER 1914) OR (MSVC_VERSION EQUAL 1914)))
target_compile_options(${ASYNCXX_SHARED_LIBRARY} PUBLIC /Zc:__cplusplus)
endif()
list(APPEND TARGET_FILES ${ASYNCXX_SHARED_LIBRARY})
endif()

if(${ASYNCXX_BUILD_STATIC})
message(STATUS "Creating static library: ${ASYNCXX_STATIC_LIBRARY}")
add_library(${ASYNCXX_STATIC_LIBRARY} STATIC ${PROJECT_SOURCE_DIR}/include/async++.h ${ASYNCXX_INCLUDE} ${ASYNCXX_SRC})
target_compile_features(${ASYNCXX_STATIC_LIBRARY} PUBLIC cxx_std_14)
# Async++ only depends on the C++11 standard libraries, but some implementations
# require the -pthread compiler flag to enable threading functionality.
if (NOT MSVC)
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PRIVATE -std=c++11)
endif()
if (APPLE)
# Use libc++ on Mac because the shipped libstdc++ version is ancient
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PRIVATE -stdlib=libc++)
set_target_properties(${ASYNCXX_STATIC_LIBRARY} PROPERTIES LINK_FLAGS -stdlib=libc++)
endif()
target_link_libraries(${ASYNCXX_STATIC_LIBRARY} PUBLIC Threads::Threads)
# Set up preprocessor definitions
target_include_directories(${ASYNCXX_STATIC_LIBRARY} PRIVATE ${PROJECT_SOURCE_DIR}/include)
set_target_properties(${ASYNCXX_STATIC_LIBRARY} PROPERTIES DEFINE_SYMBOL LIBASYNC_BUILD)
target_compile_definitions(${ASYNCXX_STATIC_LIBRARY} PUBLIC LIBASYNC_STATIC)
# Enable warnings for strict C++ standard conformance
if (NOT MSVC)
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PRIVATE -Wall -Wextra -pedantic)
endif()
# Async++ doesn't make use of RTTI information, so don't generate it.
# There are issues on Apple platforms with exceptions and -fno-rtti, so keep it
# enabled there.
# See https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti
if (MSVC)
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PRIVATE /GR-)
elseif(NOT APPLE)
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PRIVATE -fno-rtti)
endif()
# Allow disabling exceptions, but warn the user about the consequences
if (NOT USE_CXX_EXCEPTIONS)
message(WARNING "Exceptions have been disabled. Any operation that would "
"throw an exception will result in a call to std::abort() instead.")
target_compile_definitions(${ASYNCXX_STATIC_LIBRARY} PUBLIC LIBASYNC_NO_EXCEPTIONS)
if (MSVC)
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PUBLIC /EHs-c-)
else()
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PUBLIC -fno-exceptions)
endif()
endif()
# /Zc:__cplusplus is required to make __cplusplus accurate
# /Zc:__cplusplus is available starting with Visual Studio 2017 version 15.7
# (according to https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus)
Expand All @@ -123,10 +192,20 @@ endif()
# (according to https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html#variable:MSVC_VERSION)
# GREATER and EQUAL are used because GREATER_EQUAL is available starting with CMake 3.7
# (according to https://cmake.org/cmake/help/v3.7/release/3.7.html#commands)
if ((MSVC) AND ((MSVC_VERSION GREATER 1914) OR (MSVC_VERSION EQUAL 1914)))
target_compile_options(Async++ PUBLIC /Zc:__cplusplus)
if ((MSVC) AND ((MSVC_VERSION GREATER 1914) OR (MSVC_VERSION EQUAL 1914)))
target_compile_options(${ASYNCXX_STATIC_LIBRARY} PUBLIC /Zc:__cplusplus)
endif()
# In *nix systems, the static library can have the same base filename
# In Windows they need different names
if(UNIX)
set_target_properties(${ASYNCXX_STATIC_LIBRARY} PROPERTIES
OUTPUT_NAME ${ASYNCXX_SHARED_LIBRARY}
)
endif()
list(APPEND TARGET_FILES ${ASYNCXX_STATIC_LIBRARY})
endif()

# Produce find_package helper config file
include(CMakePackageConfigHelpers)
configure_package_config_file("${CMAKE_CURRENT_LIST_DIR}/Async++Config.cmake.in"
"${PROJECT_BINARY_DIR}/Async++Config.cmake"
Expand All @@ -139,22 +218,26 @@ install(FILES "${PROJECT_BINARY_DIR}/Async++Config.cmake"

# Install the library and produce a CMake export script
include(GNUInstallDirs)
install(TARGETS Async++
EXPORT Async++
install(TARGETS ${TARGET_FILES}
EXPORT asyncxx-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
FRAMEWORK DESTINATION Frameworks
)
export(EXPORT Async++)
install(EXPORT Async++ DESTINATION cmake)
export(EXPORT asyncxx-targets)
install(EXPORT asyncxx-targets DESTINATION cmake)
if (APPLE AND BUILD_FRAMEWORK)
set_target_properties(Async++ PROPERTIES OUTPUT_NAME Async++ FRAMEWORK ON)
set_target_properties(${ASYNCXX_SHARED_LIBRARY} PROPERTIES OUTPUT_NAME Async++ FRAMEWORK ON)
set_source_files_properties(${ASYNCXX_INCLUDE} PROPERTIES MACOSX_PACKAGE_LOCATION Headers/async++)
set_source_files_properties(${PROJECT_SOURCE_DIR}/include/async++.h PROPERTIES MACOSX_PACKAGE_LOCATION Headers)
else()
set_target_properties(Async++ PROPERTIES OUTPUT_NAME async++)
target_include_directories(Async++ INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
if(${ASYNCXX_BUILD_SHARED})
target_include_directories(${ASYNCXX_SHARED_LIBRARY} INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
endif()
if(${ASYNCXX_BUILD_STATIC})
target_include_directories(${ASYNCXX_STATIC_LIBRARY} INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include>)
endif()
install(FILES ${PROJECT_SOURCE_DIR}/include/async++.h DESTINATION include)
install(FILES ${ASYNCXX_INCLUDE} DESTINATION include/async++)
endif()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Supported Platforms
The only requirement to use Async++ is a C++11 compiler and standard library. Unfortunately C++11 is not yet fully implemented on most platforms. Here is the list of OS and compiler combinations which are known to work.

- Linux: Works with GCC 4.7+, Clang 3.2+ and Intel compiler 15+.
- FreeBSD 13+: Works with Clang from base system.
- Mac: Works with Apple Clang (using libc++). GCC also works but you must get a recent version (4.7+).
- iOS: Works with Apple Clang (using libc++). Note: because iOS has no thread local support, the library uses a workaround based on pthreads.
- Windows: Works with GCC 4.8+ (with pthread-win32) and Visual Studio 2013+.
Expand Down