# # D++ (DPP), The Lightweight C++ Discord Library # # Copyright 2021 Craig Edwards # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Check for various C functions check_cxx_symbol_exists(prctl "sys/prctl.h" HAVE_PRCTL) check_cxx_symbol_exists(pthread_setname_np "pthread.h" HAVE_PTHREAD_SETNAME_NP) # Go into more detail here and identify the valid signature of pthread_setname_np, # because different systems have different forms of this function (ugh). if (HAVE_PTHREAD_SETNAME_NP) include(CheckCXXSourceCompiles) check_cxx_source_compiles(" #include int main() { pthread_setname_np(\"ThreadName\"); return 0; }" HAVE_SINGLE_PARAMETER_SETNAME_NP) check_cxx_source_compiles(" #include int main() { pthread_setname_np(pthread_self(), \"ThreadName\"); return 0; }" HAVE_TWO_PARAMETER_SETNAME_NP) endif() add_compile_definitions(DPP_OS=${CMAKE_SYSTEM_NAME}) if(${AVX_TYPE} STREQUAL "OFF") include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/DetectArchitecture.cmake") else() message("-- AVX type overridden by configuration: ${AVX_TYPE}") endif() STRING(REPLACE "AVX" "" AVX_TYPE ${AVX_TYPE}) add_compile_definitions(AVX_TYPE=${AVX_TYPE}) add_compile_options(${AVX_FLAG}) if(NOT BUILD_SHARED_LIBS) if(UNIX) message("-- Building ${Green}static${ColourReset} library.") if(UNIX AND NOT APPLE) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") message("-- INFO: Changed lib suffix to ${CMAKE_FIND_LIBRARY_SUFFIXES}") endif() set(OPENSSL_USE_STATIC_LIBS TRUE) set(OPUS_USE_STATIC_LIBS TRUE) else() message(WARNING "-- Building of static library not supported on non UNIX systems.") endif() else() message("-- Building ${Green}dynamic${ColourReset} library.") endif() if (CONAN_EXPORTED) message("-- INFO: ${Green}Conan detected${ColourReset}... finding packages...") find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto) find_package(ZLIB REQUIRED) find_package(Opus) find_package(Threads REQUIRED) find_package(Git QUIET) endif() if(WIN32 AND NOT MINGW) # Fake an ssl version number to satisfy MLSPP set(OPENSSL_VERSION "1.1.1f") if (NOT WINDOWS_32_BIT) message("-- Building for windows with precompiled packaged dependencies") #set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) if (NOT CONAN_EXPORTED) set(ZLIB_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib") set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../win32/include") set(OPENSSL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../win32/include") set(OPENSSL_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib") link_libraries("${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/libssl.lib") link_libraries("${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/libcrypto.lib") link_libraries("${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/zlib.lib") link_libraries("${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/opus.lib") set(OPUS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../win32/include") set(OPUS_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/opus.lib") set(HAVE_OPUS_OPUS_H "${CMAKE_CURRENT_SOURCE_DIR}/../win32/include/opus/opus.h") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../win32/include") endif() set(OPUS_FOUND 1) add_compile_options("/bigobj") add_compile_definitions(OPENSSL_SYS_WIN32) add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS) add_compile_definitions(WIN32_LEAN_AND_MEAN) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) add_compile_definitions(_CRT_NONSTDC_NO_DEPRECATE) endif() endif() if (UNIX) message("-- Checking for ability to update autogenerated files") execute_process( COMMAND which php RESULT_VARIABLE HAS_PHP OUTPUT_QUIET ) if (${HAS_PHP} STREQUAL "0") message("-- Checking for update to autogenerated files") # target for rebuild of cluster::*_sync() functions execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." COMMAND php buildtools/make_struct.php "\\Dpp\\Generator\\SyncGenerator" ) set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/cluster_sync_calls.h" PROPERTIES GENERATED TRUE ) # target for unicode_emojis.h execute_process( WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." COMMAND php buildtools/emojis.php ) set_source_files_properties( "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/unicode_emojis.h" PROPERTIES GENERATED TRUE ) else() message("-- Autogeneration is not available") endif() endif() if (BUILD_VOICE_SUPPORT) if (MINGW OR NOT WIN32) include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/FindOpus.cmake") endif() if(HAVE_OPUS_OPUS_H) message("-- Found Opus ${Green}${OPUS_LIBRARIES}${ColourReset}") add_compile_definitions(HAVE_VOICE) set(HAVE_VOICE 1) endif() if(HAVE_VOICE) message("-- Detected ${Green}libopus${ColourReset}. VOICE support will be ${Green}enabled${ColourReset}") else(HAVE_VOICE) message("-- Could not detect ${Green}libopus${ColourReset}. VOICE support will be ${Red}disabled${ColourReset}") endif(HAVE_VOICE) else() message("-- Voice support disabled by cmake option") endif() string(ASCII 27 Esc) set(THREADS_PREFER_PTHREAD_FLAG ON) if (NOT CONAN_EXPORTED) find_package(Threads REQUIRED) endif() if(MINGW OR NOT WIN32) if (NOT CONAN_EXPORTED) find_package(ZLIB REQUIRED) endif() message("-- ZLIB: ${Green}${ZLIB_LIBRARIES}${ColourReset}") endif(MINGW OR NOT WIN32) if (NOT CONAN_EXPORTED) if(APPLE) if(CMAKE_APPLE_SILICON_PROCESSOR EQUAL arm64) set(OPENSSL_ROOT_DIR "/opt/homebrew/opt/openssl") else() set(OPENSSL_ROOT_DIR "/usr/local/opt/openssl") endif() find_package(OpenSSL REQUIRED) else() if(MINGW OR NOT WIN32) if(NOT BUILD_SHARED_LIBS) set(OPENSSL_USE_STATIC_LIBS TRUE) endif() find_package(OpenSSL REQUIRED) endif() endif() endif() include_directories(${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIRS}) if (NOT CONAN_EXPORTED) find_package(Git QUIET) endif() if(NOT GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../.git") message(FATAL_ERROR "You are using a git version of D++ but do not have git installed. Install git (not 'gh') and try again.") endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../.git") message("-- Building ${Green}git${ColourReset} version. ${Green}Be aware git versions may be unstable!${ColourReset}") else() message("-- Building ${Green}stable${ColourReset} version ${Green}${DPP_VERSION}${ColourReset}") endif() if(UNIX OR MSYS) find_program(LDCONFIG_EXECUTABLE "ldconfig") endif() if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /sdl /DFD_SETSIZE=1024") if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /Od /DEBUG /Zi") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /Oi /Oy /Gy") endif() if(NOT DPP_CLANG_CL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Zc:preprocessor") if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL") endif() endif() string(REGEX REPLACE "/W[1|2|3|4]" "/W3" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wno-unused-private-field -Wno-psabi -Wempty-body -Wignored-qualifiers -Wimplicit-fallthrough -Wmissing-field-initializers -Wsign-compare -Wtype-limits -Wuninitialized -Wshift-negative-value -pthread") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og") if (NOT MINGW) add_link_options("-rdynamic") endif () endif() set(modules_dir "../src") file(GLOB subdirlist ${modules_dir}/dpp) if (HAVE_VOICE) add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../mlspp" "mlspp") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../mlspp/include") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../mlspp/lib/bytes/include") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../mlspp/lib/hpke/include") endif() foreach (fullmodname ${subdirlist}) get_filename_component(modname ${fullmodname} NAME) set (modsrc "") if (HAVE_VOICE) file(GLOB modsrc "${modules_dir}/dpp/*.cpp" "${modules_dir}/dpp/voice/enabled/*.cpp" "${modules_dir}/dpp/dave/*.cpp" "${modules_dir}/dpp/events/*.cpp" "${modules_dir}/dpp/cluster/*.cpp" "${modules_dir}/dpp/*.rc") else() file(GLOB modsrc "${modules_dir}/dpp/*.cpp" "${modules_dir}/dpp/voice/stub/*.cpp" "${modules_dir}/dpp/events/*.cpp" "${modules_dir}/dpp/cluster/*.cpp" "${modules_dir}/dpp/*.rc") endif() if(BUILD_SHARED_LIBS) add_library(${modname} SHARED ${modsrc}) else() add_library(${modname} STATIC ${modsrc}) endif() set_target_properties(${modname} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION} SOVERSION ${CMAKE_PROJECT_VERSION} POSITION_INDEPENDENT_CODE true ) target_include_directories(${modname} PUBLIC $ $ ) get_target_property(dirs ${modname} INCLUDE_DIRECTORIES) message(STATUS "include directories of target ${modname}: ${dirs}") add_custom_target(dfkdjf COMMAND ${CMAKE_COMMAND} -E echo 'dirs: ${dirs}') if (DPP_USE_PCH) target_precompile_headers(${modname} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/cluster.h" "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/json.h" "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/utility.h" "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/restresults.h" ) endif() if (WIN32 AND NOT MINGW AND NOT CONAN_EXPORTED) if (NOT WINDOWS_32_BIT) target_link_libraries(${modname} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/libssl.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/libcrypto.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/opus.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/lib/zlib.lib") else() target_link_libraries(${modname} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/lib/libssl.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/lib/libcrypto.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/lib/opus.lib" "${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/lib/zlib.lib") endif() else() if (CONAN_EXPORTED) target_link_libraries(${modname} PUBLIC openssl::openssl ZLIB::ZLIB Opus::opus) else() target_link_libraries(${modname} PUBLIC ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ${ZLIB_LIBRARIES}) endif() if (MINGW) target_link_libraries(${modname} PUBLIC wsock32 ws2_32 crypt32) endif () endif() if (HAVE_VOICE) target_link_libraries(${modname} PUBLIC ${OPUS_LIBRARIES}) include_directories(${OPUS_INCLUDE_DIRS}) endif() endforeach() if (HAVE_VOICE) # Private statically linked dependencies if(NOT BUILD_SHARED_LIBS AND NOT APPLE) target_link_libraries(dpp PRIVATE mlspp.a mls_vectors.a bytes.a tls_syntax.a hpke.a ) message("-- INFO: Linking static dependencies") else() target_link_libraries(dpp PRIVATE mlspp mls_vectors bytes tls_syntax hpke ) message("-- INFO: Linking dynamic dependencies") endif() endif() target_compile_features(dpp PUBLIC cxx_std_17) target_compile_features(dpp PRIVATE cxx_constexpr) target_compile_features(dpp PRIVATE cxx_auto_type) target_compile_features(dpp PRIVATE cxx_defaulted_functions) target_compile_features(dpp PRIVATE cxx_deleted_functions) target_compile_features(dpp PRIVATE cxx_final) target_compile_features(dpp PRIVATE cxx_lambdas) target_compile_features(dpp PRIVATE cxx_override) target_compile_features(dpp PRIVATE cxx_thread_local) target_compile_features(dpp PRIVATE cxx_variadic_templates) target_compile_features(dpp PRIVATE cxx_attribute_deprecated) if(HAVE_PRCTL) target_compile_definitions(dpp PRIVATE HAVE_PRCTL) endif() if(HAVE_PTHREAD_SETNAME_NP) target_compile_definitions(dpp PRIVATE HAVE_PTHREAD_SETNAME_NP) endif() if(DPP_CORO) message("-- ${Yellow}Enabled coroutine feature${ColourReset}") set(CMAKE_CXX_STANDARD 20) target_compile_features(dpp PUBLIC cxx_std_20) if(WIN32 AND NOT MINGW AND NOT DPP_CLANG_CL) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /await:strict") # https://learn.microsoft.com/en-us/cpp/build/reference/await-enable-coroutine-support?view=msvc-170 else() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.0.0) # clang >= 14 has native support message("-- ${Yellow}Clang < 14 - attempting to detect if using libc++ or stdc++${ColourReset}") check_cxx_source_compiles(" #include int a = #ifdef __GLIBCXX__ 1; #else fgsfds; #endif int main(int argc, char* argv[]) { return 0; } " IS_GLIBCXX) if(IS_GLIBCXX) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0.0) message(FATAL_ERROR "${BoldRed}Clang with stdc++ and coroutines requires version 12.0.0 or above${ColourReset}") endif() message("-- ${Yellow}Detected stdc++ - enabling mock std::experimental namespace${ColourReset}") target_compile_definitions(dpp PUBLIC "STDCORO_GLIBCXX_COMPAT") else() message("-- ${Yellow}Detected libc++ - using ${ColourReset}") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0.0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines-ts") endif() endif() message("-- ${Yellow}Note - coroutines in clang < 14 are experimental, upgrading is recommended${ColourReset}") endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0) message(FATAL_ERROR "${BoldRed}Coroutines with g++ require version 10 or above${ColourReset}") elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0) message("-- ${Yellow}Note - coroutines in g++10 are experimental, upgrading to g++11 or above is recommended${ColourReset}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines") endif() endif() endif() target_compile_definitions(dpp PUBLIC DPP_CORO) execute_process(WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.." COMMAND php buildtools/make_struct.php "\\Dpp\\Generator\\CoroGenerator") endif() if(DPP_FORMATTERS) target_compile_definitions(dpp PUBLIC DPP_FORMATTERS) endif() if (NOT BUILD_SHARED_LIBS) add_library(dppstatic STATIC $ $ $ $ $ $ ) if (HAVE_VOICE) target_link_libraries(dppstatic ${ZLIB_LIBRARIES} ${OPENSSL_LIBRARIES} ${OPUS_LIBRARIES} -static-libgcc -static-libstdc++) else() target_link_libraries(dppstatic ${ZLIB_LIBRARIES} ${OPENSSL_LIBRARIES}) endif() endif() if (DPP_BUILD_TEST) enable_testing(${CMAKE_CURRENT_SOURCE_DIR}/..) file(GLOB testnamelist "${CMAKE_CURRENT_SOURCE_DIR}/../src/*") foreach (fulltestname ${testnamelist}) get_filename_component(testname ${fulltestname} NAME) if (NOT "${testname}" STREQUAL "dpp") message("-- Configuring test: ${Green}${testname}${ColourReset} with source: ${modules_dir}/${testname}/*.cpp") set (testsrc "") file(GLOB testsrc "${modules_dir}/${testname}/*.cpp") add_executable(${testname} ${testsrc}) if (DPP_CORO OR DPP_FORMATTERS) target_compile_features(${testname} PRIVATE cxx_std_20) else() target_compile_features(${testname} PRIVATE cxx_std_17) endif() if (MSVC) target_compile_options(${testname} PRIVATE /utf-8) endif() if(BUILD_SHARED_LIBS) target_link_libraries(${testname} PUBLIC ${modname}) else() target_link_libraries(${testname} PUBLIC dppstatic) endif() endif() endforeach() add_test( NAME unittest COMMAND unittest ) endif() if (NOT CONAN_EXPORTED) if(WIN32 AND NOT MINGW) if (NOT WINDOWS_32_BIT) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/bin/zlib1.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/bin/libcrypto-1_1-x64.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/bin/libssl-1_1-x64.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/bin/opus.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) else() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/bin/zlib1.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/bin/libcrypto-1_1.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/bin/libssl-1_1.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../win32/32/bin/opus.dll" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" COPYONLY) endif() endif() endif() if(DPP_INSTALL) if(NOT WIN32) # Installation include(GNUInstallDirs) install(TARGETS dpp LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) message("Library install directory at ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") install(DIRECTORY ../include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) message("Include files install directory at ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -DRUN_LDCONFIG=${RUN_LDCONFIG} -DLDCONFIG_EXECUTABLE=${LDCONFIG_EXECUTABLE} -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/PostInstall.cmake)") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../dpp.pc.in" "${CMAKE_BINARY_DIR}/dpp.pc" @ONLY) install(FILES "${CMAKE_BINARY_DIR}/dpp.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") elseif(MINGW) install(TARGETS dpp LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(DIRECTORY ../include/ DESTINATION ${CMAKE_INSTALL_PREFIX}/include) endif() # Setup information for packaging and distribution include("${CMAKE_CURRENT_SOURCE_DIR}/../cmake/CPackSetup.cmake") # CPack initialization for distribution include(CPack) endif()