From 9bca3270bca30e6dbd8069d5871f164a8b72ad30 Mon Sep 17 00:00:00 2001 From: Joseph Henry Date: Tue, 2 Mar 2021 01:53:03 -0800 Subject: [PATCH] Overhaul build system and documentation --- CMakeLists.txt | 1015 ++++++++++++++++++++++++-------------------- Makefile | 127 ------ README | 23 + README.md | 430 ++++--------------- build.ps1 | 206 +++++++++ build.sh | 543 ++++++++++++++++++++++++ dist.ps1 | 175 -------- dist.sh | 737 -------------------------------- examples/README.md | 58 +-- 9 files changed, 1409 insertions(+), 1905 deletions(-) delete mode 100644 Makefile create mode 100644 README create mode 100644 build.ps1 create mode 100755 build.sh delete mode 100644 dist.ps1 delete mode 100755 dist.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e9fd3d..e385805 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,60 +2,222 @@ cmake_minimum_required(VERSION 3.0) project(zt) find_package(Threads) -set(requiredlibs) - -if(CENTRAL_API) - find_package(CURL) - if(CURL_FOUND) - include_directories(${CURL_INCLUDE_DIR}) - set(requiredlibs ${requiredlibs} ${CURL_LIBRARIES}) - else(CURL_FOUND) - message( - FATAL_ERROR "Could not find the CURL library and development files.") - endif(CURL_FOUND) -endif() - # ----------------------------------------------------------------------------- -# | PLATFORM/FEATURE AND IDE DETECTION | +# | PLATFORM DETECTION | # ----------------------------------------------------------------------------- -if(${CMAKE_SYSTEM_NAME} MATCHES "Android") - set(BUILDING_ANDROID TRUE) +# Apple +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(BUILD_DARWIN TRUE) endif() + +# macOS +if(BUILD_DARWIN AND NOT BUILD_IOS_FRAMEWORK) + set(BUILD_MACOS TRUE) +endif() + +if(${CMAKE_GENERATOR} STREQUAL "Xcode") + set(IN_XCODE TRUE) + set(XCODE_EMIT_EFFECTIVE_PLATFORM_NAME ON) +endif() + +# Target names +if(IN_XCODE) + set(XCODE_FRAMEWORK_NAME ${PROJECT_NAME}) +endif() + +# Windows if(WIN32) - set(BUILDING_WIN32 TRUE) + set(BUILD_WIN32 TRUE) endif() if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)") - set(BUILDING_WIN64 TRUE) + set(BUILD_WIN64 TRUE) endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set(BUILDING_DARWIN TRUE) +if(BUILD_WIN32 + OR BUILD_WIN64 + OR MSVC) + set(BUILD_WIN TRUE) endif() -if(IOS_FRAMEWORK) - set(BUILDING_IOS TRUE) + +# Linux +# if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + +# ----------------------------------------------------------------------------- +# | SOURCE DIRECTORIES | +# ----------------------------------------------------------------------------- + +set(PROJ_DIR ${PROJECT_SOURCE_DIR}) +set(LWIP_SRC_DIR "${PROJ_DIR}/ext/lwip/src") +set(ZTO_SRC_DIR "${PROJ_DIR}/ext/ZeroTierOne") +set(LIBZT_SRC_DIR "${PROJ_DIR}/src") +set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin) +set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +set(INTERMEDIATE_LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/intermediate) +if(UNIX) + set(LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/unix/port) endif() -if(BUILDING_DARWIN AND NOT IOS_FRAMEWORK) - set(BUILDING_MACOS TRUE) + +if(BUILD_WIN) + set(LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/win32) endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(BUILDING_LINUX TRUE) + +# ----------------------------------------------------------------------------- +# | INCLUDE DIRECTORIES | +# ----------------------------------------------------------------------------- + +# ZeroTier +include_directories(${ZTO_SRC_DIR}) +include_directories(${ZTO_SRC_DIR}/include) +include_directories(${ZTO_SRC_DIR}/node) +include_directories(${ZTO_SRC_DIR}/osdep) +# ZeroTier (ext) +include_directories(${ZTO_SRC_DIR}/ext/miniupnpc) +include_directories(${ZTO_SRC_DIR}/ext/libnatpmp) +# libzt +include_directories(${PROJ_DIR}/src) +include_directories(${PROJ_DIR}/include) +# libzt (ext) +include_directories(${PROJ_DIR}/ext/concurrentqueue) +include_directories(${LWIP_SRC_DIR}/include) +include_directories(${LWIP_PORT_DIR}/include) + +# ----------------------------------------------------------------------------- +# | TARGET AND VARIANT SELECTION | +# ----------------------------------------------------------------------------- + +# C# language bindings (libzt.dll/dylib/so) +if (ZTS_ENABLE_PINVOKE) + # Features + set(BUILD_STATIC_LIB FALSE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_EXAMPLES FALSE) + set(BUILD_HOST_SELFTEST FALSE) + set(INSTALLABLE FALSE) + # Sources and libraries + set(ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cpp) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PINVOKE=1") endif() -if(${CMAKE_GENERATOR} STREQUAL "Xcode") - set(IN_XCODE TRUE) - set(XCODE_EMIT_EFFECTIVE_PLATFORM_NAME ON) + +# Python language bindings (_libzt.so) +if (ZTS_ENABLE_PYTHON) + # Features + set(ZTS_ENABLE_PYTHON TRUE) + #set(ZTS_ENABLE_STATS FALSE) + # Targets + set(BUILD_STATIC_LIB FALSE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_EXAMPLES FALSE) + set(BUILD_HOST_SELFTEST FALSE) + set(INSTALLABLE FALSE) + # Sources and libraries + find_package(PythonLibs REQUIRED) + include_directories(${PYTHON_INCLUDE_DIRS}) + set(ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/python/*.cpp) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_PYTHON=1") endif() -if(BUILDING_WIN32 - OR BUILDING_WIN64 - OR MSVC) - set(BUILDING_WIN TRUE) + +# Java language bindings +if (ZTS_ENABLE_JAVA) + set(BUILD_STATIC_LIB FALSE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_HOST_EXAMPLES FALSE) + set(BUILD_HOST_SELFTEST FALSE) + set(ZTS_ENABLE_STATS FALSE) + set(INSTALLABLE FALSE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_JAVA=1") endif() -if(NOT BUILDING_ANDROID AND NOT IN_XCODE) - set(SHOULD_BUILD_TESTS TRUE) + +# All native targets for this host +if(BUILD_HOST) + set(BUILD_STATIC_LIB TRUE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_HOST_EXAMPLES TRUE) + set(BUILD_HOST_SELFTEST TRUE) + set(ZTS_ENABLE_STATS TRUE) + set(INSTALLABLE TRUE) endif() -if(BUILDING_WIN32 - OR BUILDING_WIN64 - OR MSVC) - set(BUILDING_WIN TRUE) + +# CI +if(BUILD_HOST_SELFTEST_ONLY) + set(BUILD_STATIC_LIB TRUE) + set(BUILD_SHARED_LIB FALSE) + set(BUILD_HOST_EXAMPLES FALSE) + set(BUILD_HOST_SELFTEST TRUE) + set(ZTS_ENABLE_STATS FALSE) + set(INSTALLABLE FALSE) +endif() + +# Android AAR containing libzt.so +if(${CMAKE_SYSTEM_NAME} MATCHES "Android") + set(BUILD_ANDROID TRUE) + set(BUILD_STATIC_LIB FALSE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_SELFTEST FALSE) + set(BUILD_EXAMPLES FALSE) + set(INSTALLABLE FALSE) +endif() + +if(BUILD_MACOS_FRAMEWORK) + set(BUILD_STATIC_LIB TRUE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_SELFTEST FALSE) + set(BUILD_EXAMPLES FALSE) + set(INSTALLABLE FALSE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") + set(CMAKE_XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)") + set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH NO) + include_directories( + "/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk/usr/include/") +endif() + +if(BUILD_IOS_FRAMEWORK) + set(BUILD_STATIC_LIB TRUE) + set(BUILD_SHARED_LIB TRUE) + set(BUILD_SELFTEST FALSE) + set(BUILD_EXAMPLES FALSE) + set(INSTALLABLE FALSE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") + set(DEVROOT + "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer") + if(IOS_ARM64) + set(CMAKE_OSX_ARCHITECTURES arm64) + set(SDKVER "11.4") + endif() + if(IOS_ARMV7) + # armv7 armv7s + set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)") + set(SDKVER "10.0") + endif() + set(SDKROOT "${DEVROOT}/SDKs/iPhoneOS${SDKVER}.sdk") + if(EXISTS ${SDKROOT}) + set(CMAKE_OSX_SYSROOT "${SDKROOT}") + else() + message("Warning, iOS Base SDK path not found: " ${SDKROOT}) + endif() +endif() + +if(ZTS_ENABLE_STATS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_ENABLE_STATS=1") +endif() + +# ----------------------------------------------------------------------------- +# | HACKS TO GET THIS TO WORK ON WINDOWS | +# ----------------------------------------------------------------------------- + +if(BUILD_WIN) + # Possibly a CMake limitation? -- Can't share target output names + set(STATIC_LIB_NAME ${PROJECT_NAME}-static) + set(STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-static) + set(DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) + set(DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-shared) +else() + set(STATIC_LIB_NAME ${PROJECT_NAME}-static) + set(STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) + set(DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) + set(DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) endif() # ----------------------------------------------------------------------------- @@ -63,380 +225,335 @@ endif() # ----------------------------------------------------------------------------- if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "debug") - set(DEBUG_BUILD ON) - set(CMAKE_VERBOSE_MAKEFILE ON) - set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) + set(BUILD_DEBUG ON) + set(CMAKE_VERBOSE_MAKEFILE ON) + set(DEBUG_OPTIMIZATION "-O3") endif() if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "release") - set(RELEASE_BUILD ON) - set(CMAKE_VERBOSE_MAKEFILE OFF) - set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin) - set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) + set(BUILD_RELEASE ON) + set(CMAKE_VERBOSE_MAKEFILE OFF) + set(RELEASE_OPTIMIZATION "-O3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wno-everything -w") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wno-everything -w") endif() -set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) -set(INTERMEDIATE_LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib/intermediate) - # ----------------------------------------------------------------------------- -# | LIBRARY NAMES | +# | EXAMPLES | # ----------------------------------------------------------------------------- -if(IN_XCODE) - set(XCODE_FRAMEWORK_NAME ${PROJECT_NAME}) -endif() +if(BUILD_HOST_EXAMPLES) + add_executable(nonblockingclient + ${PROJ_DIR}/examples/cpp/nonblockingclient.cpp) + target_link_libraries(nonblockingclient ${STATIC_LIB_NAME}) -if(BUILDING_WIN) - # Possibly a CMake limitation? -- Can't share target output names - set(STATIC_LIB_NAME ${PROJECT_NAME}-static) - set(STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-static) - set(DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) - set(DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}-shared) -else() - set(STATIC_LIB_NAME ${PROJECT_NAME}-static) - set(STATIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) - set(DYNAMIC_LIB_NAME ${PROJECT_NAME}-shared) - set(DYNAMIC_LIB_OUTPUT_NAME ${PROJECT_NAME}) + add_executable(nonblockingserver + ${PROJ_DIR}/examples/cpp/nonblockingserver.cpp) + target_link_libraries(nonblockingserver ${STATIC_LIB_NAME}) + + add_executable(earthtest + ${PROJ_DIR}/examples/cpp/earthtest.cpp) + target_link_libraries(earthtest ${STATIC_LIB_NAME}) + + add_executable(adhoc + ${PROJ_DIR}/examples/cpp/adhoc.cpp) + target_link_libraries(adhoc ${STATIC_LIB_NAME}) + + add_executable(comprehensive + ${PROJ_DIR}/examples/cpp/comprehensive.cpp) + target_link_libraries(comprehensive ${STATIC_LIB_NAME}) + + add_executable(client + ${PROJ_DIR}/examples/cpp/client.cpp) + target_link_libraries(client ${STATIC_LIB_NAME}) + + add_executable(server + ${PROJ_DIR}/examples/cpp/server.cpp) + target_link_libraries(server ${STATIC_LIB_NAME}) + + add_executable(keymanagement + ${PROJ_DIR}/examples/cpp/keymanagement.cpp) + target_link_libraries(keymanagement ${STATIC_LIB_NAME}) + + if(CENTRAL_API) + add_executable(centralapi ${PROJ_DIR}/examples/cpp/centralapi.cpp) + target_link_libraries(centralapi ${STATIC_LIB_NAME}) + endif() endif() # ----------------------------------------------------------------------------- # | FLAGS | # ----------------------------------------------------------------------------- -set(SILENCE "${SILENCE} -Wno-unused-parameter") -set(SILENCE "${SILENCE} -Wno-format") -set(SILENCE "${SILENCE} -Wno-tautological-constant-out-of-range-compare ") -set(SILENCE "${SILENCE} -Wno-macro-redefined") -set(SILENCE "${SILENCE} -Wno-parentheses-equality") -set(SILENCE "${SILENCE} -Wno-sign-compare") -set(SILENCE "${SILENCE} -Wno-unused-variable") -set(SILENCE "${SILENCE} -Wno-missing-field-initializers") -set(SILENCE "${SILENCE} -Wno-unused-parameter") - set(ZT_FLAGS "${ZT_FLAGS} -DZT_USE_MINIUPNPC=1") set(ZT_FLAGS "${ZT_FLAGS} -DZT_SOFTWARE_UPDATE_DEFAULT=0") set(ZT_FLAGS "${ZT_FLAGS} -D_USING_LWIP_DEFINITIONS_=0") set(ZT_FLAGS "${ZT_FLAGS} -DZT_SDK=1") -if(DEBUG_BUILD) - set(LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_DBG_TYPES_ON=128") - set(LWIP_FLAGS "${LWIP_FLAGS} -DSOCKETS_DEBUG=128") - # set (LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_STATS_LARGE=1") set (LWIP_FLAGS - # "${LWIP_FLAGS} -DLWIP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DLINK_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DETHARP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DIPFRAG_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DIP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DICMP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DIGMP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DUDP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DTCP_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DSYS_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DIP6_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DICMP6_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DIP6_FRAG_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DMLD6_STATS=1") - set(LWIP_FLAGS "${LWIP_FLAGS} -DND6_STATS=1") +if(BUILD_DEBUG) + set(LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_DBG_TYPES_ON=128") + set(LWIP_FLAGS "${LWIP_FLAGS} -DSOCKETS_DEBUG=128") + # set (LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_STATS_LARGE=1") set (LWIP_FLAGS + # "${LWIP_FLAGS} -DLWIP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DLINK_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DETHARP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DIPFRAG_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DIP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DICMP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DIGMP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DUDP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DTCP_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DSYS_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DIP6_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DICMP6_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DIP6_FRAG_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DMLD6_STATS=1") + set(LWIP_FLAGS "${LWIP_FLAGS} -DND6_STATS=1") else() - set(LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_DBG_TYPES_ON=0") + set(LWIP_FLAGS "${LWIP_FLAGS} -DLWIP_DBG_TYPES_ON=0") endif() -set(DEBUG_OPTIMIZATION "-O3") -set(RELEASE_OPTIMIZATION "-O3") - -if(BUILDING_WIN) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNOMINMAX") +if(BUILD_WIN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNOMINMAX") else() - set(CMAKE_C_FLAGS - "${CMAKE_C_FLAGS} \ + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} \ ${ZT_FLAGS} \ -fstack-protector") - set(CMAKE_C_FLAGS_DEBUG - "${CMAKE_C_FLAGS_DEBUG} \ + set(CMAKE_C_FLAGS_DEBUG + "${CMAKE_C_FLAGS_DEBUG} \ ${DEBUG_OPTIMIZATION} \ -DLWIP_DEBUG=1 -DLIBZT_DEBUG=1") - set(CMAKE_C_FLAGS_RELEASE - "${SILENCE} \ - ${CMAKE_C_FLAGS_RELEASE} \ + set(CMAKE_C_FLAGS_RELEASE + "${CMAKE_C_FLAGS_RELEASE} \ ${RELEASE_OPTIMIZATION} \ -fstack-protector") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ ${ZT_FLAGS} -Wall -Wextra -std=c++11") - set(CMAKE_CXX_FLAGS_DEBUG - "${CMAKE_CXX_FLAGS_DEBUG} \ + set(CMAKE_CXX_FLAGS_DEBUG + "${CMAKE_CXX_FLAGS_DEBUG} \ ${DEBUG_OPTIMIZATION} \ -DLWIP_DEBUG=1 -DLIBZT_DEBUG=1") - set(CMAKE_CXX_FLAGS_RELEASE - "${CMAKE_CXX_FLAGS_RELEASE} \ - ${SILENCE} \ + set(CMAKE_CXX_FLAGS_RELEASE + "${CMAKE_CXX_FLAGS_RELEASE} \ ${RELEASE_OPTIMIZATION}") endif() # WINDOWS-specific MSVC flags and libraries -if(BUILDING_WIN) - # 32-bit - if(NOT BUILDING_WIN64) - set(WINLIBDIR, - "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x86") - endif() - # 64-bit - if(BUILDING_WIN64) - set(WINLIBDIR, - "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x64") - endif() - # find_library (ws2_32_LIBRARY_PATH NAMES WS2_32 HINTS ${WINLIBDIR}) - # find_library (shlwapi_LIBRARY_PATH NAMES ShLwApi HINTS ${WINLIBDIR}) - set(ws2_32_LIBRARY_PATH "${WINLIBDIR}/WS2_32.Lib") - set(shlwapi_LIBRARY_PATH "${WINLIBDIR}/ShLwApi.Lib") - set(iphlpapi_LIBRARY_PATH "${WINLIBDIR}/iphlpapi.Lib") - message(STATUS ${WINLIBDIR}) - message(STATUS "WS2_32=${ws2_32_LIBRARY_PATH}") - message(STATUS "ShLwApi=${shlwapi_LIBRARY_PATH}") - message(STATUS "liphlpapi=${iphlpapi_LIBRARY_PATH}") - add_definitions(-DZT_SDK=1) - add_definitions(-DADD_EXPORTS=1) +if(BUILD_WIN) + # 32-bit + if(NOT BUILD_WIN64) + set(WINLIBDIR, + "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x86") + endif() + # 64-bit + if(BUILD_WIN64) + set(WINLIBDIR, + "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.16299.0/um/x64") + endif() + # find_library (ws2_32_LIBRARY_PATH NAMES WS2_32 HINTS ${WINLIBDIR}) + # find_library (shlwapi_LIBRARY_PATH NAMES ShLwApi HINTS ${WINLIBDIR}) + set(ws2_32_LIBRARY_PATH "${WINLIBDIR}/WS2_32.Lib") + set(shlwapi_LIBRARY_PATH "${WINLIBDIR}/ShLwApi.Lib") + set(iphlpapi_LIBRARY_PATH "${WINLIBDIR}/iphlpapi.Lib") + message(STATUS ${WINLIBDIR}) + message(STATUS "WS2_32=${ws2_32_LIBRARY_PATH}") + message(STATUS "ShLwApi=${shlwapi_LIBRARY_PATH}") + message(STATUS "liphlpapi=${iphlpapi_LIBRARY_PATH}") + add_definitions(-DZT_SDK=1) + add_definitions(-DADD_EXPORTS=1) +endif() + +# ----------------------------------------------------------------------------- +# | OPTIONAL FEATURES | +# ----------------------------------------------------------------------------- + +if(CENTRAL_API) + set(requiredlibs) + find_package(CURL) + if(CURL_FOUND) + include_directories(${CURL_INCLUDE_DIR}) + set(requiredlibs ${requiredlibs} ${CURL_LIBRARIES}) + else(CURL_FOUND) + message( + FATAL_ERROR "Could not find the CURL library and development files.") + endif(CURL_FOUND) endif() # ----------------------------------------------------------------------------- # | JNI | # ----------------------------------------------------------------------------- -if(SDK_JNI OR BUILDING_ANDROID) - message(STATUS "Looking for JNI") +if(ZTS_ENABLE_JAVA OR BUILD_ANDROID) + message(STATUS "Looking for JNI") - if(BUILDING_WIN) - # We are only interested in finding jni.h: we do not care about extended JVM - # functionality or the AWT library. set(JAVA_AWT_LIBRARY NotNeeded) - # set(JAVA_JVM_LIBRARY NotNeeded) set(JAVA_INCLUDE_PATH2 NotNeeded) - # set(JAVA_AWT_INCLUDE_PATH NotNeeded) - set(JAVA_INCLUDE_PATH "C:\\Program Files\\Java\\jdk-10.0.2\\include") - endif() + if(BUILD_WIN) + # We are only interested in finding jni.h: we do not care about extended JVM + # functionality or the AWT library. set(JAVA_AWT_LIBRARY NotNeeded) + # set(JAVA_JVM_LIBRARY NotNeeded) set(JAVA_INCLUDE_PATH2 NotNeeded) + # set(JAVA_AWT_INCLUDE_PATH NotNeeded) + set(JAVA_INCLUDE_PATH "C:\\Program Files\\Java\\jdk-10.0.2\\include") + endif() - set(JAVA_AWT_LIBRARY NotNeeded) - set(JAVA_JVM_LIBRARY NotNeeded) - set(JAVA_INCLUDE_PATH2 NotNeeded) - set(JAVA_AWT_INCLUDE_PATH NotNeeded) - find_package(JNI REQUIRED) + set(JAVA_AWT_LIBRARY NotNeeded) + set(JAVA_JVM_LIBRARY NotNeeded) + set(JAVA_INCLUDE_PATH2 NotNeeded) + set(JAVA_AWT_INCLUDE_PATH NotNeeded) + find_package(JNI REQUIRED) - if(JNI_FOUND) - message(STATUS "JNI_INCLUDE_DIR=${JNI_INCLUDE_DIRS}") - message(STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}") - list(GET JNI_INCLUDE_DIRS 0 JNI_INCLUDE_DIR) - message(STATUS "jni path=${JNI_INCLUDE_DIR}") - include_directories("${JNI_INCLUDE_DIR}") - # include_directories ("${JNI_INCLUDE_DIRS}") - if(BUILDING_WIN) - include_directories("${JNI_INCLUDE_DIR}\\win32") - endif() - if(BUILDING_MACOS) - include_directories("${JNI_INCLUDE_DIR}/darwin") - endif() - if(BUILDING_LINUX) - include_directories("${JNI_INCLUDE_DIR}/linux") - endif() - else() - message(STATUS "JNI not found") - endif() - if(JNI_FOUND) - add_definitions(-DSDK_JNI=1) - endif() -endif() # SDK_JNI + if(JNI_FOUND) + message(STATUS "JNI_INCLUDE_DIR=${JNI_INCLUDE_DIRS}") + message(STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}") + list(GET JNI_INCLUDE_DIRS 0 JNI_INCLUDE_DIR) + message(STATUS "jni path=${JNI_INCLUDE_DIR}") + include_directories("${JNI_INCLUDE_DIR}") + # include_directories ("${JNI_INCLUDE_DIRS}") + if(BUILD_WIN) + include_directories("${JNI_INCLUDE_DIR}\\win32") + endif() + if(BUILD_MACOS) + include_directories("${JNI_INCLUDE_DIR}/darwin") + endif() + if(BUILD_LINUX) + include_directories("${JNI_INCLUDE_DIR}/linux") + endif() + else() + message(STATUS "JNI not found") + endif() + if(JNI_FOUND) + add_definitions(-DZTS_ENABLE_JAVA=1) + endif() +endif() # ZTS_ENABLE_JAVA # ----------------------------------------------------------------------------- # | SOURCES | # ----------------------------------------------------------------------------- -set(PROJ_DIR ${PROJECT_SOURCE_DIR}) -set(LWIP_SRC_DIR "${PROJ_DIR}/ext/lwip/src") -set(ZTO_SRC_DIR "${PROJ_DIR}/ext/ZeroTierOne") -set(LIBZT_SRC_DIR "${PROJ_DIR}/src") - file(GLOB ztcoreSrcGlob ${ZTO_SRC_DIR}/node/*.cpp - ${ZTO_SRC_DIR}/osdep/OSUtils.cpp ${ZTO_SRC_DIR}/osdep/PortMapper.cpp - ${ZTO_SRC_DIR}/osdep/ManagedRoute.cpp) + ${ZTO_SRC_DIR}/osdep/OSUtils.cpp ${ZTO_SRC_DIR}/osdep/PortMapper.cpp + ${ZTO_SRC_DIR}/osdep/ManagedRoute.cpp) file(GLOB libnatpmpSrcGlob ${ZTO_SRC_DIR}/ext/libnatpmp/natpmp.c - ${ZTO_SRC_DIR}/ext/libnatpmp/wingettimeofday.c - ${ZTO_SRC_DIR}/ext/libnatpmp/getgateway.c) + ${ZTO_SRC_DIR}/ext/libnatpmp/wingettimeofday.c + ${ZTO_SRC_DIR}/ext/libnatpmp/getgateway.c) +if(NOT BUILD_WIN) +list(REMOVE_ITEM libnatpmpSrcGlob ${ZTO_SRC_DIR}/ext/libnatpmp/wingettimeofday.c) +endif() file( - GLOB - libminiupnpcSrcGlob - ${ZTO_SRC_DIR}/ext/miniupnpc/connecthostport.c - ${ZTO_SRC_DIR}/ext/miniupnpc/igd_desc_parse.c - ${ZTO_SRC_DIR}/ext/miniupnpc/minisoap.c - ${ZTO_SRC_DIR}/ext/miniupnpc/minissdpc.c - ${ZTO_SRC_DIR}/ext/miniupnpc/miniupnpc.c - ${ZTO_SRC_DIR}/ext/miniupnpc/miniwget.c - ${ZTO_SRC_DIR}/ext/miniupnpc/minixml.c - ${ZTO_SRC_DIR}/ext/miniupnpc/portlistingparse.c - ${ZTO_SRC_DIR}/ext/miniupnpc/receivedata.c - ${ZTO_SRC_DIR}/ext/miniupnpc/upnpcommands.c - ${ZTO_SRC_DIR}/ext/miniupnpc/upnpdev.c - ${ZTO_SRC_DIR}/ext/miniupnpc/upnperrors.c - ${ZTO_SRC_DIR}/ext/miniupnpc/upnpreplyparse.c) - -if(ZTS_PINVOKE) - set(ZTS_SWIG_WRAPPER_FILE ${LIBZT_SRC_DIR}/bindings/csharp/*.cxx) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_PINVOKE=1") -endif() + GLOB + libminiupnpcSrcGlob + ${ZTO_SRC_DIR}/ext/miniupnpc/connecthostport.c + ${ZTO_SRC_DIR}/ext/miniupnpc/igd_desc_parse.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minisoap.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minissdpc.c + ${ZTO_SRC_DIR}/ext/miniupnpc/miniupnpc.c + ${ZTO_SRC_DIR}/ext/miniupnpc/miniwget.c + ${ZTO_SRC_DIR}/ext/miniupnpc/minixml.c + ${ZTO_SRC_DIR}/ext/miniupnpc/portlistingparse.c + ${ZTO_SRC_DIR}/ext/miniupnpc/receivedata.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpcommands.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpdev.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnperrors.c + ${ZTO_SRC_DIR}/ext/miniupnpc/upnpreplyparse.c) file(GLOB libztSrcGlob ${LIBZT_SRC_DIR}/*.cpp ${ZTS_SWIG_WRAPPER_FILE}) -if(UNIX) - set(LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/unix/port) -endif() - -if(BUILDING_WIN) - set(LWIP_PORT_DIR ${PROJ_DIR}/ext/lwip-contrib/ports/win32) -endif() - file( - GLOB - lwipSrcGlob - ${LWIP_SRC_DIR}/netif/*.c - ${LWIP_SRC_DIR}/api/*.c - ${LWIP_PORT_DIR}/sys_arch.c - ${LWIP_SRC_DIR}/core/*.c - ${LWIP_SRC_DIR}/core/ipv4/*.c - ${LWIP_SRC_DIR}/core/ipv6/*.c) + GLOB + lwipSrcGlob + ${LWIP_SRC_DIR}/netif/*.c + ${LWIP_SRC_DIR}/api/*.c + ${LWIP_PORT_DIR}/sys_arch.c + ${LWIP_SRC_DIR}/core/*.c + ${LWIP_SRC_DIR}/core/ipv4/*.c + ${LWIP_SRC_DIR}/core/ipv6/*.c) list(REMOVE_ITEM lwipSrcGlob ${LWIP_SRC_DIR}/netif/slipif.c) # header globs for xcode frameworks file(GLOB frameworkPublicHeaderGlob include/ZeroTierSockets.h) file(GLOB frameworkHeaderGlob ${frameworkPublicHeaderGlob} - ${frameworkPrivateHeaderGlob}) - -# ----------------------------------------------------------------------------- -# | INCLUDES | -# ----------------------------------------------------------------------------- - -include_directories(${ZTO_SRC_DIR}) -include_directories(${ZTO_SRC_DIR}/node) -include_directories(${ZTO_SRC_DIR}/osdep) -include_directories(${ZTO_SRC_DIR}/include) -include_directories(${ZTO_SRC_DIR}/ext/miniupnpc) -include_directories(${ZTO_SRC_DIR}/ext/libnatpmp) -include_directories(${PROJ_DIR}/src) -include_directories(${PROJ_DIR}/include) -include_directories(${LWIP_SRC_DIR}/include) -include_directories(${LWIP_PORT_DIR}/include) -include_directories(${PROJ_DIR}/ext/concurrentqueue) - -# TODO: Should separate this into its own ios.cmake file - -if(IOS_FRAMEWORK) - # Controllers probably won't be run from iPhones, so we can omit JSON support - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") - set(DEVROOT - "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer" - ) - if(IOS_ARM64) - set(CMAKE_OSX_ARCHITECTURES arm64) - set(SDKVER "11.4") - endif() - if(IOS_ARMV7) - # armv7 armv7s - set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)") - set(SDKVER "10.0") - endif() - - set(SDKROOT "${DEVROOT}/SDKs/iPhoneOS${SDKVER}.sdk") - if(EXISTS ${SDKROOT}) - set(CMAKE_OSX_SYSROOT "${SDKROOT}") - else() - message("Warning, iOS Base SDK path not found: " ${SDKROOT}) - endif() -endif() - -if(MACOS_FRAMEWORK) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOMIT_JSON_SUPPORT=1") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOMIT_JSON_SUPPORT=1") - set(CMAKE_XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)") - set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH NO) - include_directories( - "/Library/Developer/CommandLineTools/SDKs/MacOSX11.0.sdk/usr/include/") -endif() + ${frameworkPrivateHeaderGlob}) # ----------------------------------------------------------------------------- # | OBJECT LIBRARIES (INTERMEDIATE) | # ----------------------------------------------------------------------------- -# zto_obj -add_library(zto_obj OBJECT ${ztcoreSrcGlob}) -set_target_properties(zto_obj PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") -if(BUILDING_WIN) - target_link_libraries(zto_obj ws2_32) - target_link_libraries(zto_obj ${shlwapi_LIBRARY_PATH}) - target_link_libraries(zto_obj ${iphlpapi_LIBRARY_PATH}) +if(BUILD_STATIC_LIB) + # zto_obj + add_library(zto_obj OBJECT ${ztcoreSrcGlob}) + set_target_properties(zto_obj PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") + if(BUILD_WIN) + target_link_libraries(zto_obj ws2_32) + target_link_libraries(zto_obj ${shlwapi_LIBRARY_PATH}) + target_link_libraries(zto_obj ${iphlpapi_LIBRARY_PATH}) + endif() + + # libnatpmp_obj + add_library(libnatpmp_obj OBJECT ${libnatpmpSrcGlob}) + set_target_properties(libnatpmp_obj PROPERTIES COMPILE_FLAGS "-DNATPMP_EXPORTS") + + # miniupnpc_obj + add_library(miniupnpc_obj OBJECT ${libminiupnpcSrcGlob}) + target_compile_definitions( + miniupnpc_obj + PRIVATE ZT_USE_MINIUPNPC + MINIUPNP_STATICLIB + _DARWIN_C_SOURCE + MINIUPNPC_SET_SOCKET_TIMEOUT + MINIUPNPC_GET_SRC_ADDR + _BSD_SOURCE + _DEFAULT_SOURCE + MINIUPNPC_VERSION_STRING=\"2.0\" + UPNP_VERSION_STRING=\"UPnP/1.1\" + ENABLE_STRNATPMPERR + OS_STRING=\"Darwin/15.0.0\") + if(BUILD_DARWIN AND NOT BUILD_IOS_FRAMEWORK) + target_compile_definitions(miniupnpc_obj PRIVATE MACOSX) + endif() + + # lwip_obj + add_library(lwip_obj OBJECT ${lwipSrcGlob}) + set_target_properties(lwip_obj PROPERTIES COMPILE_FLAGS "${LWIP_FLAGS}") + + # libzt_obj + add_library(libzt_obj OBJECT ${libztSrcGlob}) + set_target_properties(libzt_obj PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") endif() -# libnatpmp_obj -add_library(libnatpmp_obj OBJECT ${libnatpmpSrcGlob}) -set_target_properties(libnatpmp_obj PROPERTIES COMPILE_FLAGS "-DNATPMP_EXPORTS") - -# miniupnpc_obj -add_library(miniupnpc_obj OBJECT ${libminiupnpcSrcGlob}) -target_compile_definitions( - miniupnpc_obj - PRIVATE ZT_USE_MINIUPNPC - MINIUPNP_STATICLIB - _DARWIN_C_SOURCE - MINIUPNPC_SET_SOCKET_TIMEOUT - MINIUPNPC_GET_SRC_ADDR - _BSD_SOURCE - _DEFAULT_SOURCE - MINIUPNPC_VERSION_STRING=\"2.0\" - UPNP_VERSION_STRING=\"UPnP/1.1\" - ENABLE_STRNATPMPERR - OS_STRING=\"Darwin/15.0.0\") -if(BUILDING_DARWIN AND NOT IOS_FRAMEWORK) - target_compile_definitions(miniupnpc_obj PRIVATE MACOSX) -endif() - -# lwip_obj -add_library(lwip_obj OBJECT ${lwipSrcGlob}) -set_target_properties(lwip_obj PROPERTIES COMPILE_FLAGS "${LWIP_FLAGS}") - -# libzt_obj -add_library(libzt_obj OBJECT ${libztSrcGlob}) -set_target_properties(libzt_obj PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") - # PIC # zto_pic add_library(zto_pic ${ztcoreSrcGlob}) set_target_properties(zto_pic PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}" - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) # libnatpmp_pic add_library(natpmp_pic ${libnatpmpSrcGlob}) set_target_properties(natpmp_pic PROPERTIES COMPILE_FLAGS "-DNATPMP_EXPORTS" - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) # miniupnpc_pic add_library(miniupnpc_pic ${libminiupnpcSrcGlob}) target_compile_definitions( - miniupnpc_pic - PRIVATE MACOSX - ZT_USE_MINIUPNPC - MINIUPNP_STATICLIB - _DARWIN_C_SOURCE - MINIUPNPC_SET_SOCKET_TIMEOUT - MINIUPNPC_GET_SRC_ADDR - _BSD_SOURCE - _DEFAULT_SOURCE - MINIUPNPC_VERSION_STRING=\"2.0\" - UPNP_VERSION_STRING=\"UPnP/1.1\" - ENABLE_STRNATPMPERR - OS_STRING=\"Darwin/15.0.0\") + miniupnpc_pic + PRIVATE MACOSX + ZT_USE_MINIUPNPC + MINIUPNP_STATICLIB + _DARWIN_C_SOURCE + MINIUPNPC_SET_SOCKET_TIMEOUT + MINIUPNPC_GET_SRC_ADDR + _BSD_SOURCE + _DEFAULT_SOURCE + MINIUPNPC_VERSION_STRING=\"2.0\" + UPNP_VERSION_STRING=\"UPnP/1.1\" + ENABLE_STRNATPMPERR + OS_STRING=\"Darwin/15.0.0\") set_target_properties(miniupnpc_pic PROPERTIES POSITION_INDEPENDENT_CODE ON) # lwip_pic @@ -447,164 +564,156 @@ set_target_properties(lwip_pic PROPERTIES COMPILE_FLAGS "${LWIP_FLAGS}") # libzt_pic add_library(zt_pic ${libztSrcGlob}) set_target_properties(zt_pic PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}" - POSITION_INDEPENDENT_CODE ON) + POSITION_INDEPENDENT_CODE ON) + +#set_property( +# TARGET lwip_pic +# APPEND +# PROPERTY STATIC_LIBRARY_FLAGS "-no_warning_for_no_symbols" +#) # ----------------------------------------------------------------------------- -# | BUILD TARGETS (FINAL PRODUCT) | +# | STATIC LIB | # ----------------------------------------------------------------------------- -# libztcore.a -add_library(ztcore STATIC $) -set_target_properties( - ztcore PROPERTIES OUTPUT_NAME ztcore LIBRARY_OUTPUT_DIRECTORY - ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) +if(BUILD_STATIC_LIB) + # libztcore.a + add_library(ztcore STATIC $) + set_target_properties( + ztcore PROPERTIES OUTPUT_NAME ztcore LIBRARY_OUTPUT_DIRECTORY + ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + # libzt.a + add_library( + ${STATIC_LIB_NAME} STATIC + $ $ + $ $ + $ ${libztSrcGlob}) + set_target_properties( + ${STATIC_LIB_NAME} + PROPERTIES LINKER_LANGUAGE CXX + OUTPUT_NAME zt + POSITION_INDEPENDENT_CODE ON + LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) + set_target_properties(${STATIC_LIB_NAME} PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") + target_link_libraries(${STATIC_LIB_NAME} ${CMAKE_THREAD_LIBS_INIT}) -# libzt.a -add_library( - ${STATIC_LIB_NAME} STATIC - $ $ - $ $ - $ ${libztSrcGlob}) -set_target_properties( - ${STATIC_LIB_NAME} - PROPERTIES OUTPUT_NAME zt - POSITION_INDEPENDENT_CODE ON - LIBRARY_OUTPUT_DIRECTORY ${INTERMEDIATE_LIBRARY_OUTPUT_PATH}) -set_target_properties(${STATIC_LIB_NAME} PROPERTIES COMPILE_FLAGS "${ZT_FLAGS}") -target_link_libraries(${STATIC_LIB_NAME} ${CMAKE_THREAD_LIBS_INIT}) + if(BUILD_WIN) + target_link_libraries(${STATIC_LIB_NAME} ${ws2_32_LIBRARY_PATH} + ${shlwapi_LIBRARY_PATH} ${iphlpapi_LIBRARY_PATH}) + endif() # BUILD_STATIC_LIB +endif() if(CENTRAL_API) - target_link_libraries(${STATIC_LIB_NAME} ${CURL_LIBRARIES}) +# target_link_libraries(${STATIC_LIB_NAME} ${CURL_LIBRARIES}) endif() -if(BUILDING_WIN) - target_link_libraries(${STATIC_LIB_NAME} ${ws2_32_LIBRARY_PATH} - ${shlwapi_LIBRARY_PATH} ${iphlpapi_LIBRARY_PATH}) -endif() -# libzt.so/dylib/dll -add_library(${DYNAMIC_LIB_NAME} SHARED ${libztSrcGlob}) -target_link_libraries(${DYNAMIC_LIB_NAME} zt_pic lwip_pic zto_pic natpmp_pic - miniupnpc_pic) -set_target_properties(${DYNAMIC_LIB_NAME} PROPERTIES COMPILE_FLAGS - "${ZT_FLAGS}") -set_target_properties( - ${DYNAMIC_LIB_NAME} PROPERTIES OUTPUT_NAME ${DYNAMIC_LIB_OUTPUT_NAME} - WINDOWS_EXPORT_ALL_SYMBOLS true) -target_link_libraries( - ${DYNAMIC_LIB_NAME} - ${CMAKE_THREAD_LIBS_INIT} - ${ws2_32_LIBRARY_PATH} - ${shlwapi_LIBRARY_PATH} - ${iphlpapi_LIBRARY_PATH} - zt_pic - lwip_pic - zto_pic - natpmp_pic - miniupnpc_pic) -if(CENTRAL_API) - target_link_libraries(${DYNAMIC_LIB_NAME} ${CURL_LIBRARIES}) -endif() +# ----------------------------------------------------------------------------- +# | SHARED LIB | +# ----------------------------------------------------------------------------- -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +if(BUILD_SHARED_LIB) + # libzt.so/dylib/dll + add_library(${DYNAMIC_LIB_NAME} SHARED ${libztSrcGlob}) + target_link_libraries(${DYNAMIC_LIB_NAME} ${PYTHON_LIBRARIES}) + target_link_libraries(${DYNAMIC_LIB_NAME} zt_pic lwip_pic zto_pic natpmp_pic + miniupnpc_pic) + set_target_properties(${DYNAMIC_LIB_NAME} + PROPERTIES COMPILE_FLAGS + "${ZT_FLAGS}") + set_target_properties( + ${DYNAMIC_LIB_NAME} PROPERTIES OUTPUT_NAME ${DYNAMIC_LIB_OUTPUT_NAME} + WINDOWS_EXPORT_ALL_SYMBOLS true) + target_link_libraries( + ${DYNAMIC_LIB_NAME} + ${CMAKE_THREAD_LIBS_INIT} + ${ws2_32_LIBRARY_PATH} + ${shlwapi_LIBRARY_PATH} + ${iphlpapi_LIBRARY_PATH} + zt_pic + lwip_pic + zto_pic + natpmp_pic + miniupnpc_pic) -if(BUILDING_ANDROID) - target_link_libraries(${DYNAMIC_LIB_NAME} android log) -endif() + if(CENTRAL_API) + target_link_libraries(${DYNAMIC_LIB_NAME} ${CURL_LIBRARIES}) + endif() + + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + + if(BUILD_ANDROID) + target_link_libraries(${DYNAMIC_LIB_NAME} android log) + endif() +endif() # BUILD_SHARED_LIB # xcode framework if(IN_XCODE) - # stdint.h is needed for API definitions but can cause conflicts in certain - # projects where integers may already be defined. Thus this flag is used to - # exclude their definition in ZeroTierSockets.h - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_NO_STDINT_H=1") + # stdint.h is needed for API definitions but can cause conflicts in certain + # projects where integers may already be defined. Thus this flag is used to + # exclude their definition in ZeroTierSockets.h + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZTS_NO_STDINT_H=1") - include_directories(${frameworkHeaderGlob}) + include_directories(${frameworkHeaderGlob}) - add_library( - ${XCODE_FRAMEWORK_NAME} STATIC - $ - $ - $ - $ - $ - ${libztSrcGlob} - ${frameworkHeaderGlob}) + add_library( + ${XCODE_FRAMEWORK_NAME} STATIC + $ + $ + $ + $ + $ + ${libztSrcGlob} + ${frameworkHeaderGlob}) - set_target_properties(${XCODE_FRAMEWORK_NAME} PROPERTIES ENABLE_BITCODE "YES") - set_target_properties(${XCODE_FRAMEWORK_NAME} - PROPERTIES BITCODE_GENERATION_MODE bitcode) - target_compile_options(${XCODE_FRAMEWORK_NAME} PUBLIC -fembed-bitcode) - target_link_libraries(${XCODE_FRAMEWORK_NAME} PUBLIC -fembed-bitcode) + set_target_properties(${XCODE_FRAMEWORK_NAME} PROPERTIES ENABLE_BITCODE "YES") + set_target_properties(${XCODE_FRAMEWORK_NAME} + PROPERTIES BITCODE_GENERATION_MODE bitcode) + target_compile_options(${XCODE_FRAMEWORK_NAME} PUBLIC -fembed-bitcode) + target_link_libraries(${XCODE_FRAMEWORK_NAME} PUBLIC -fembed-bitcode) - set_target_properties( - ${XCODE_FRAMEWORK_NAME} - PROPERTIES - FRAMEWORK YES - FRAMEWORK_VERSION A - XCODE_ATTRIBUTE_DEFINES_MODULE YES - MACOSX_FRAMEWORK_IDENTIFIER com.cmake.${XCODE_FRAMEWORK_NAME} - XCODE_ATTRIBUTE_MODULEMAP_FILE "${PROJ_DIR}/ports/module.modulemap" - PUBLIC_HEADER "${frameworkHeaderGlob}" - XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer" - XCODE_ATTRIBUTE_CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES YES) + set_target_properties( + ${XCODE_FRAMEWORK_NAME} + PROPERTIES + FRAMEWORK YES + FRAMEWORK_VERSION A + XCODE_ATTRIBUTE_DEFINES_MODULE YES + MACOSX_FRAMEWORK_IDENTIFIER com.cmake.${XCODE_FRAMEWORK_NAME} + XCODE_ATTRIBUTE_MODULEMAP_FILE "${PROJ_DIR}/pkg/apple/module.modulemap" + PUBLIC_HEADER "${frameworkHeaderGlob}" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer" + XCODE_ATTRIBUTE_CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES YES) endif() # ----------------------------------------------------------------------------- -# | EXECUTABLES | +# | SELFTEST | # ----------------------------------------------------------------------------- -if(SHOULD_BUILD_TESTS) - add_executable(earthtest ${PROJ_DIR}/examples/cpp/earthtest.cpp) - target_link_libraries(earthtest ${STATIC_LIB_NAME}) - add_executable(adhoc ${PROJ_DIR}/examples/cpp/adhoc.cpp) - target_link_libraries(adhoc ${STATIC_LIB_NAME}) - add_executable(comprehensive ${PROJ_DIR}/examples/cpp/comprehensive.cpp) - target_link_libraries(comprehensive ${STATIC_LIB_NAME}) - add_executable(client ${PROJ_DIR}/examples/cpp/client.cpp) - target_link_libraries(client ${STATIC_LIB_NAME}) - add_executable(server ${PROJ_DIR}/examples/cpp/server.cpp) - target_link_libraries(server ${STATIC_LIB_NAME}) - add_executable(nonblockingclient - ${PROJ_DIR}/examples/cpp/nonblockingclient.cpp) - target_link_libraries(nonblockingclient ${STATIC_LIB_NAME}) - add_executable(nonblockingserver - ${PROJ_DIR}/examples/cpp/nonblockingserver.cpp) - target_link_libraries(nonblockingserver ${STATIC_LIB_NAME}) - add_executable(keymanagement ${PROJ_DIR}/examples/cpp/keymanagement.cpp) - target_link_libraries(keymanagement ${STATIC_LIB_NAME}) - if(CENTRAL_API) - add_executable(centralapi ${PROJ_DIR}/examples/cpp/centralapi.cpp) - target_link_libraries(centralapi ${STATIC_LIB_NAME}) - endif() +if(BUILD_HOST_SELFTEST) + add_executable(selftest ${PROJ_DIR}/test/selftest.cpp) + target_link_libraries(selftest ${STATIC_LIB_NAME}) + project(TEST) + enable_testing() + add_test(NAME selftest COMMAND selftest) endif() # ----------------------------------------------------------------------------- # | INSTALL | # ----------------------------------------------------------------------------- -set(PUBLIC_ZT_HEADERS ${PROJECT_SOURCE_DIR}/include/ZeroTierSockets.h) - -set_target_properties(${STATIC_LIB_NAME} PROPERTIES PUBLIC_HEADER - "${PUBLIC_ZT_HEADERS}") -install( - TARGETS ${STATIC_LIB_NAME} - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - PUBLIC_HEADER DESTINATION include) -install( - TARGETS ${DYNAMIC_LIB_NAME} - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) - -# ----------------------------------------------------------------------------- -# | CI TESTS | -# ----------------------------------------------------------------------------- - -add_executable(errortest ${PROJ_DIR}/test/error.cpp) -target_link_libraries(errortest ${STATIC_LIB_NAME}) -project(TEST) -enable_testing() -add_test(NAME MyTest COMMAND errortest) +if(INSTALLABLE) + set(PUBLIC_ZT_HEADERS ${PROJECT_SOURCE_DIR}/include/ZeroTierSockets.h) + set_target_properties(${STATIC_LIB_NAME} PROPERTIES PUBLIC_HEADER + "${PUBLIC_ZT_HEADERS}") + install( + TARGETS ${STATIC_LIB_NAME} + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include) + install( + TARGETS ${DYNAMIC_LIB_NAME} + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib) +endif() \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 0806da5..0000000 --- a/Makefile +++ /dev/null @@ -1,127 +0,0 @@ -DIST_BUILD_SCRIPT := ./dist.sh - -#EXECUTABLES = cmake -#build_reqs := $(foreach exec,$(EXECUTABLES),\ -# $(if $(shell which $(exec)),some string,$(error "No $(exec) in PATH"))) - -.PHONY: list -list: - @$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | awk -v RS= \ - -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") \ - {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs - -# Pull all submodules -update: - @git submodule update --init - @git submodule status - -# Patch submodules (issue update first) -patch: - #-cd ext/lwip; git apply ../lwip.patch; - #-cd ext/lwip-contrib; git apply ../lwip-contrib.patch; - #-cd ext/ZeroTierOne; git apply ../ZeroTierOne.patch; - -# Target-specific clean -clean_ios: - -rm -rf ports/xcode_ios - -rm -rf ports/xcode_ios_simulator -clean_macos: - -rm -rf ports/xcode_macos -clean_android: - -rm -rf pkg/android/app/build - -find pkg -name ".externalNativeBuild" -exec rm -r "{}" \; - $(DIST_BUILD_SCRIPT) android "clean" -clean_products: - -rm -rf products -.PHONY: clean -clean: clean_ios clean_macos clean_android - $(DIST_BUILD_SCRIPT) clean - -# Use CMake generators to build projects from CMakeLists.txt -projects: - $(DIST_BUILD_SCRIPT) generate_projects - -# Android -android_debug: - $(DIST_BUILD_SCRIPT) android "debug" - $(DIST_BUILD_SCRIPT) clean_android_project - $(DIST_BUILD_SCRIPT) prep_android_example "debug" -android_release: - $(DIST_BUILD_SCRIPT) android "release" - $(DIST_BUILD_SCRIPT) clean_android_project - $(DIST_BUILD_SCRIPT) prep_android_example "release" -android: android_debug android_release -prep_android_debug_example: - $(DIST_BUILD_SCRIPT) prep_android_example "debug" -prep_android_release_example: - $(DIST_BUILD_SCRIPT) prep_android_example "release" - -# macOS -macos_debug: - $(DIST_BUILD_SCRIPT) macos "debug" -macos_release: - $(DIST_BUILD_SCRIPT) macos "release" -macos: macos_debug macos_release - -# xcframework -xcframework: - xcodebuild -project ports/apple/zt.xcodeproj archive -scheme zt -sdk macosx -archivePath build/macosx - xcodebuild -project ports/apple/zt.xcodeproj archive -scheme zt -sdk iphoneos -archivePath build/iphoneos - xcodebuild -project ports/apple/zt.xcodeproj archive -scheme zt -sdk iphonesimulator -archivePath build/iphonesimulator - - xcodebuild -create-xcframework \ - -framework build/macosx.xcarchive/Products/Library/Frameworks/zt.framework \ - -framework build/iphoneos.xcarchive/Products/Library/Frameworks/zt.framework \ - -framework build/iphonesimulator.xcarchive/Products/Library/Frameworks/zt.framework \ - -output lib/zt.xcframework - - rm -rf build/macosx.xcarchive - rm -rf build/iphoneos.xcarchive - rm -rf build/iphonesimulator.xcarchive - -# iOS -ios_debug: - $(DIST_BUILD_SCRIPT) ios "debug" -ios_release: - $(DIST_BUILD_SCRIPT) ios "release" -ios: ios_debug ios_release - -# Host -host_release: - $(DIST_BUILD_SCRIPT) host "release" -host_debug: - $(DIST_BUILD_SCRIPT) host "debug" -host_clean: - $(DIST_BUILD_SCRIPT) host "clean" -host_jar_debug: - $(DIST_BUILD_SCRIPT) host_jar "debug" -host_jar_release: - $(DIST_BUILD_SCRIPT) host_jar "release" -host_jar: host_jar_debug host_jar_release - -host_pinvoke_release: - $(DIST_BUILD_SCRIPT) host_pinvoke "release" -host_pinvoke_debug: - $(DIST_BUILD_SCRIPT) host_pinvoke "debug" -host_pinvoke: host_pinvoke_release host_pinvoke_debug - -host: host_debug host_release - -# Build every target available on this host -all: host host_pinvoke host_jar macos ios android - $(DIST_BUILD_SCRIPT) display - -# [For distribution process only] Prepare remote builds -wrap: - $(DIST_BUILD_SCRIPT) wrap - -# Binary distribution -bdist: - $(DIST_BUILD_SCRIPT) merge - $(DIST_BUILD_SCRIPT) bdist - -# Source distribution -sdist: update patch - $(DIST_BUILD_SCRIPT) sdist - -dist: bdist sdist diff --git a/README b/README new file mode 100644 index 0000000..8a9bca1 --- /dev/null +++ b/README @@ -0,0 +1,23 @@ + + +-------------------------------------------------------------------------------- + libzt --- Encrypted P2P SD-WAN library by ZeroTier +-------------------------------------------------------------------------------- + +This project uses cmake as a build system generator. The scripts build.sh and +build.ps1 are used to simplify building and packaging for various targets. + + dist/ : Finished targets: libraries, binaries, packages, etc. + cache/ : Build system caches that can safely be deleted after build. + pkg/ : Project, script and spec files to generate packages. + +1. git submodule update --init +2. (*)nix : ./build.sh host "release" +2. Windows : . .\build.ps1; Build-Host -BuildType "Release" + +To see additional build targets: + +./build.sh list + +Help, bugs, and feature requests: https://github.com/zerotier/libzt/issues + diff --git a/README.md b/README.md index 92a027d..e858668 100644 --- a/README.md +++ b/README.md @@ -1,390 +1,108 @@ -# ZeroTier SDK -Connect physical devices, virtual devices, and application instances as if everything is on a single LAN. -*** +
+

ZeroTier SDK

+Peer-to-peer and cross-platform encrypted connections built right into your app or service. No drivers, no root, and no host configuration. -The ZeroTier SDK brings your network into user-space. We've paired our network hypervisor core with a network stack ([lwIP](https://savannah.nongnu.org/projects/lwip/)) to provide your application with an exclusive and private virtual network interface. All traffic on this interface is end-to-end encrypted between each peer and we provide an easy-to-use socket interface derived from [Berkeley Sockets](https://en.wikipedia.org/wiki/Berkeley_sockets). Since we aren't using the kernel's network stack that means, no drivers, no root, and no host configuration requirements. For a more in-depth discussion on the technical side of ZeroTier, check out our [Manual](https://www.zerotier.com/manual.shtml). For troubleshooting advice see our [Knowledgebase](https://zerotier.atlassian.net/wiki/spaces/SD/overview). If you need further assistance, create an account at [my.zerotier.com](https://my.zerotier.com) and join our community of users and professionals. +
-Downloads: [download.zerotier.com/dist/sdk](https://download.zerotier.com/dist/sdk) +Examples | +API Documentation | +Community | +FAQ | +Report a Bug -
+
-## Building on Linux, macOS -*Requires [CMake](https://cmake.org/download/), [Clang](https://releases.llvm.org/download.html) is recommended* -``` -git submodule update --init -make host_release CC=clang CXX=clang++ -``` +latest libzt version +Last Commit +Build Status (master branch) +
-## Building on Windows -*Requires [CMake](https://cmake.org/download/) and [PowerShell](https://github.com/powershell/powershell)* +| Language/Platform | Installation | Version | Example | +|:----------|:---------|:---|:---| +| C/C++ | [Build from source](./BUILDING.md) | version|[C/C++](./examples/cpp) | +| Objective-C | See [examples/objective-c](./examples/objective-c) | version |[Objective-C](./examples/objective-c) | +| C# | `Install-Package ZeroTier.Sockets` | |[C#](./examples/csharp) | +| Python | `pip install libzt`| |[Python](./examples/python) | +| Rust | Coming Soon | version|[Rust](./examples/rust) | +| Swift | See [examples/swift](./examples/swift) |version |[Swift](./examples/swift) | +| Java | See [examples/java](./examples/java) | |[Java](./examples/java) | +| Node.js | See [examples/nodejs](./examples/nodejs) ||[Node.js](./examples/nodejs) | +| Linux | [Build from source](#build-from-source) | version| [C/C++](./examples/cpp) | +| macOS | `brew install libzt`| | [C/C++](./examples/cpp), [Objective-C](./examples/objective-c) | +| iOS / iPadOS | [zt.framework]() | | [Objective-C](./examples/objective-c), [Swift](./examples/swift) | +| Android | [zt.aar]() | | [Java](./examples/java) | -``` -git submodule update --init -. ./dist.ps1 -Build-Library -BuildType "Release" -Arch "Win32|x64|ARM|ARM64" -LanguageBinding "none|csharp" -``` +
-*Note: To build both `release` and `debug` libraries for only your host's architecture use `make host`. Or optionally `make host_release` for release only. To build everything including things like iOS frameworks, Android packages, etc, use `make all`. Possible build targets can be seen by using `make list`. Resultant libraries will be placed in `./lib`, test and example programs will be placed in `./bin`* - -Typical build output: - -``` -lib -├── release -| └── linux-x86_64 -| ├── libzt.a -| └── libzt.so -└── debug - └── ... -bin -└── release - └── linux-x86_64 - ├── client - └── server -``` - -Example linking step: - -``` -clang++ -o yourApp yourApp.cpp -L./lib/release/linux-x86_64/ -lzt; ./yourApp -``` - -
- -## Starting ZeroTier - -The next few sections explain how to use the network control interface portion of the API. These functions are non-blocking and will return an error code specified in the [Error Handling](#error-handling) section and will result in the generation of callback events detailed in the [Event Handling](#event-handling) section. It is your responsibility to handle these events. To start the service, simply call: - -`zts_start(char *path, void (*userCallbackFunc)(struct zts_callback_msg*), int port)` - -At this stage, if a cryptographic identity for this node does not already exist on your local storage medium, it will generate a new one and store it, the node's address (commonly referred to as `nodeId`) will be derived from this identity and will be presented to you upon receiving the `ZTS_EVENT_NODE_ONLINE` shown below. The first argument `path` is a path where you will direct ZeroTier to store its automatically-generated cryptographic identity files (`identity.public` and `identity.secret`), these files are your keys to communicating on the network. Keep them safe and keep them unique. If any two nodes are online using the same identities you will have a bad time. The second argument `userCallbackFunc` is a function that you specify to handle all generated events for the life of your program, see below: +
``` #include "ZeroTierSockets.h" -... - -bool networkReady = false; - -void on_zts_event(struct zts_callback_msg *msg) -{ - if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { - printf("ZTS_EVENT_NODE_ONLINE, nodeId=%llx\n", msg->node->address); - networkReady = true; - } - ... -} - int main() { - zts_start("configPath", &on_zts_event, 9994); - uint64_t nwid = 0x0123456789abcdef; - while (!networkReady) { sleep(1); } - zts_join(nwid); - int fd = zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0); + zts_start(...) + zts_join(networkId); + zts_socket(ZTS_AF_INET, ZTS_SOCK_STREAM, 0); + zts_connect(...); ... - return 0; -} - -``` - -For more complete examples see `./examples/` - -
- -After calling `zts_start()` you will receive one or more events specified in the [Node Events](#node-events) section. After receiving `ZTS_EVENT_NODE_ONLINE` you will be allowed to join or leave networks. You must authorize the node ID provided by the this callback event to join your network. This can be done manually or via our [Web API](https://my.zerotier.com/help/api). Note however that if you are using an Ad-hoc network, it has no controller and therefore requires no authorization. - -At the end of your program or when no more network activity is anticipated, the user application can shut down the service with `zts_stop()`. However, it is safe to leave the service running in the background indefinitely as it doesn't consume much memory or CPU while at idle. `zts_stop()` is a non-blocking call and will itself issue a series of events indicating that various aspects of the ZeroTier service have successfully shut down. - -It is worth noting that while `zts_stop()` will stop the service, the user-space network stack will continue operating in a headless hibernation mode. This is intended behavior due to the fact that the network stack we've chosen doesn't currently support the notion of shutdown since it was initially designed for embedded applications that are simply switched off. If you do need a way to shut everything down and free all resources you can call `zts_free()`, but please note that calling this function will prevent all subsequent `zts_start()` calls from succeeding and will require a full application restart if you want to run the service again. The events `ZTS_EVENT_NODE_ONLINE` and `ZTS_EVENT_NODE_OFFLINE` can be seen periodically throughout the lifetime of your application depending on the reliability of your underlying network link, these events are lagging indicators and are typically only triggered every thirty (30) seconds. - -Lastly, the function `zts_restart()` is provided as a way to restart the ZeroTier service along with all of its virtual interfaces. The network stack will remain online and undisturbed during this call. Note that this call will temporarily block until the service has fully shut down, then will return and you may then watch for the appropriate startup callbacks mentioned above. - -
- -## Joining a network - -Joining a ZeroTier virtual network is as easy as calling `zts_join(uint64_t networkId)`. Similarly there is a `zts_leave(uint64_t networkId)`. Note that `zts_start()` must be called and a `ZTS_EVENT_NODE_ONLINE` event must have been received before these calls will succeed. After calling `zts_join()` any one of the events detailed in the [Network Events](#network-events) section may be generated. - -
- -## Connecting and communicating with peers - -Creating a standard socket connection generally works the same as it would using an ordinary socket interface, however with ZeroTier there is a subtle difference in how connections are established which may cause confusion. Since ZeroTier employs transport-triggered link provisioning a direct connection between peers will not exist until contact has been attempted by at least one peer. During this time before a direct link is available traffic will be handled via our free relay service. The provisioning of this direct link usually only takes a couple of seconds but it is important to understand that if you attempt something like s `zts_connect(...)` call during this time it may fail due to packet loss. Therefore it is advised to repeatedly call `zts_connect(...)` until it succeeds and to wait to send additional traffic until `ZTS_EVENT_PEER_DIRECT` has been received for the peer you are attempting to communicate with. All of the above is optional, but it will improve your experience. - -`tl;dr: Try a few times and wait a few seconds` - -As a mitigation for the above behavior, ZeroTier will by default cache details about how to contact a peer in the `peers.d` subdirectory of the config path you passed to `zts_start(...)`. In scenarios where paths do not often change, this can almost completely eliminate the issue and will make connections nearly instantaneous. If however you do not wish to cache these details you can disable it via `zts_set_peer_caching(false)`. - -
- -## Event handling - -As mentioned in previous sections, the control API works by use of non-blocking calls and the generation of a few dozen different event types. Depending on the type of event there may be additional contextual information attached to the `zts_callback_msg` object that you can use. This contextual information will be housed in one of the following structures which are defined in `include/ZeroTierSockets.h`: - -``` -struct zts_callback_msg -{ - int eventCode; - struct zts_node_details *node; - struct zts_network_details *network; - struct zts_netif_details *netif; - struct zts_virtual_network_route *route; - struct zts_peer_details *peer; - struct zts_addr_details *addr; -}; -``` - -Here's an example of a callback function: - -``` -void on_zts_event(struct zts_callback_msg *msg) -{ - if (msg->eventCode == ZTS_EVENT_NODE_ONLINE) { - printf("ZTS_EVENT_NODE_ONLINE, node=%llx\n", msg->node->address); - // You can join networks now! - } } ``` -In this callback function you can perform additional non-blocking API calls or other work. While not returning control to the service isn't forbidden (the event messages are generated by a separate thread) it is recommended that you return control as soon as possible as not returning will prevent the user application from receiving additional callback event messages which may be time-sensitive. - -
- -A typical ordering of messages may look like the following: +# Build from source ``` -... -ZTS_EVENT_NODE_ONLINE // Your node is ready to be used. -ZTS_EVENT_ADDR_ADDED_IP4 // Your node received an IP address assignment on a given network. -ZTS_EVENT_NETWORK_UPDATE // Something about a network changed. -ZTS_EVENT_NETWORK_READY_IP4 // Your node has joined a network, has an address, and can send/receive traffic. -ZTS_EVENT_PEER_RELAY // A peer was discovered but no direct path exists (yet.) -... -ZTS_EVENT_PEER_DIRECT // One or more direct paths to a peer were discovered. +git submodule update --init ``` -## Node Events +This project uses [CMake](https://cmake.org/download/) as a build system generator. The scripts `build.*` simplify building and packaging for various targets. There are many targets and configurations not mentioned here. -Accessible via `msg->node` as a `zts_node_details` object, this message type will contain information about the status of your node. *Possible values of `msg->eventCode`:* +|Platform| Build instructions | Notes | +|:---|:---|:---| +|Linux | `./build.sh host "release"`| [build.sh](./build.sh) | +|macOS | `./build.sh host "release"`| [build.sh](./build.sh) | +|Windows | `. .\build.ps1; Build-Host -BuildType "Release"`| [build.ps1](./build.ps1), *Requires [PowerShell](https://github.com/powershell/powershell)*| + +Using the `host` keyword will automatically detect the current machine type and build standard libzt for use in C/C++ (no additional language bindings.) See `./build.sh list` for additional target options. + +Example output: ``` -ZTS_EVENT_NODE_OFFLINE // Your node is offline. -ZTS_EVENT_NODE_ONLINE // Your node is online and ready to communicate! -ZTS_EVENT_NODE_DOWN // The node is down (for any reason.) -ZTS_EVENT_NODE_IDENTITY_COLLISION // There is another node with the same identity causing a conflict. -ZTS_EVENT_NODE_UNRECOVERABLE_ERROR // Something went wrong internally. -ZTS_EVENT_NODE_NORMAL_TERMINATION // Your node has terminated. +~/libzt/dist/macos-x64-host-release +├── bin +│   ├── client +│   ├── server +│   └── ... +└── lib + ├── libzt.a + └── libzt.dylib ``` -*Example contents of `msg->node`:* +Important directories: -``` -id : f746d550dd -version : 1.4.6 -primaryPort : 9995 -secondaryPort : 0 -``` +|Directory| Purpose| +|:---|:---| +|`dist`| Contains finished targets (libraries, binaries, packages, etc.)| +|`cache`| Contains build system caches that can safely be deleted after use.| +|`pkg`| Contains project, script and spec files to generate packages.| -## Network Events +# Self-hosting (Optional) -Accessible via `msg->network` as a `zts_network_details` object, this message type will contain information about the status of a particular network your node has joined. *Possible values of `msg->eventCode`:* +We provide ways for your app or enterprise to function indepenently from any of our services if desired. -``` -ZTS_EVENT_NETWORK_NOT_FOUND // The network does not exist. The provided networkID may be incorrect. -ZTS_EVENT_NETWORK_CLIENT_TOO_OLD // This client is too old. -ZTS_EVENT_NETWORK_REQ_CONFIG // Waiting for network config, this might take a few seconds. -ZTS_EVENT_NETWORK_OK // Node successfully joined. -ZTS_EVENT_NETWORK_ACCESS_DENIED // The network is private. Your node requires authorization. -ZTS_EVENT_NETWORK_READY_IP4 // Your node successfully received an IPv4 address. -ZTS_EVENT_NETWORK_READY_IP6 // Your node successfully received an IPv6 address. -ZTS_EVENT_NETWORK_DOWN // For some reason the network is no longer available. -ZTS_EVENT_NETWORK_UPDATE // The network's config has changed: mtu, name, managed route, etc. -``` +While we do operate a global network of redundant root servers, network controllers and an admin API/UI called [Central](https://my.zerotier.com), some use-cases require full control over the infrastructure and we try to make it as easy as possible to set up your own controllers and root servers: See [here](https://github.com/zerotier/ZeroTierOne/tree/master/controller) to learn more about how to set up your own network controller, and [here](https://www.zerotier.com/manual/#4_4) to learn more about setting up your own roots. -*Example contents of `msg->network`:* +# Help -``` -nwid : 8bd712bf36bdae5f -mac : ae53fa031fcf -name : cranky_hayes -type : 0 -mtu : 2800 -dhcp : 0 -bridge : 0 -broadcastEnabled : 1 -portError : 0 -netconfRevision : 34 -routeCount : 1 -multicastSubscriptionCount : 1 -- mac=ffffffffffff, adi=ac1b2561 -addresses: -- FC5D:69B6:E0F7:46D5:50DD::1 -- 172.27.37.97 -routes: -- target : 172.27.0.0 -- via : 0.0.0.0 - - flags : 0 - - metric : 0 -``` + - Reference: [C API](./include/README.md) + - Examples: [examples/](./examples) + - Bug reports: [Open a github issue](https://github.com/zerotier/libzt/issues). + - General ZeroTier troubleshooting: [Knowledgebase](https://zerotier.atlassian.net/wiki/spaces/SD/overview). + - Talk to us: + - Community: [discuss.zerotier.com](https://discuss.zerotier.com) + - @zerotier + - r/zerotier -
- -## Peer Events - -Accessible via `msg->peer` as a `zts_peer_details` object, this message type will contain information about a peer that was discovered by your node. These events are triggered when the reachability status of a peer has changed. *Possible values of `msg->eventCode`:* - -``` -ZTS_EVENT_PEER_DIRECT // At least one direct path to this peer is known. -ZTS_EVENT_PEER_RELAY // No direct path to this peer is known. It will be relayed, (high packet loss and jitter.) -ZTS_EVENT_PEER_UNREACHABLE // Peer is not reachable by any means. -ZTS_EVENT_PEER_PATH_DISCOVERED // A new direct path to this peer has been discovered. -ZTS_EVENT_PEER_PATH_DEAD // A direct path to this peer has expired. -``` - -*Example contents of `msg->peer`:* - -``` -peer : a747d5502d -role : 0 -latency : 4 -version : 1.4.6 -pathCount : 2 - - 172.27.37.97 - - F75D:69B6:E0C7:47D5:51DB::1 -``` - -## Address Events - -Accessible via `msg->addr` as a `zts_addr_details` object, this message type will contain information about addresses assign to your node on a particular network. The information contained in these events is also available via `ZTS_EVENT_NETWORK_UPDATE` events. *Possible values of `msg->eventCode`:* - -``` -ZTS_EVENT_ADDR_ADDED_IP4 // A new IPv4 address was assigned to your node on the indicated network. -ZTS_EVENT_ADDR_REMOVED_IP4 // An IPv4 address assignment to your node was removed on the indicated network. -ZTS_EVENT_ADDR_ADDED_IP6 // A new IPv6 address was assigned to your node on the indicated network. -ZTS_EVENT_ADDR_REMOVED_IP6 // An IPv6 address assignment to your node was removed on the indicated network. -``` - -*Example contents of `msg->addr`:* - -``` -nwid : a747d5502d -addr : 172.27.37.97 -``` - -
- -## Error handling - -Calling a `zts_*` function will result in one of the following return codes. Only when `ZTS_ERR` is returned will `zts_errno` be set. Its values closely mirror those used in standard socket interfaces and are defined in `include/ZeroTierSockets.h`. - -``` -ZTS_ERR_OK // No error -ZTS_ERR_SOCKET // Socket error (see zts_errno for more information) -ZTS_ERR_SERVICE // General ZeroTier internal error. Maybe you called something out of order? -ZTS_ERR_ARG // An argument provided is invalid. -ZTS_ERR_NO_RESULT // Call succeeded but no result was available. Not necessarily an error. -ZTS_ERR_GENERAL // General internal failure. Consider filing a bug report. -``` - -*NOTE: For Android/Java (or similar) which use JNI, the socket API's error codes are negative values encoded in the return values of function calls* -*NOTE: For protocol-level errors (such as dropped packets) or internal network stack errors, see the section `Statistics`* - -
- -## Common pitfalls - - - If you have started a node but have not received a `ZTS_EVENT_NODE_ONLINE`: - - You may need to view our [Router Config Tips](https://zerotier.atlassian.net/wiki/spaces/SD/pages/6815768/Router+Configuration+Tips) knowledgebase article. Sometimes this is due to firewall/NAT settings. - - - If you have received a `ZTS_EVENT_NODE_ONLINE` event and attempted to join a network but do not see your node ID in the network panel on [my.zerotier.com](my.zerotier.com) after some time: - - You may have typed in your network ID incorrectly. - - Used an improper integer representation for your network ID (e.g. `int` instead of `uint64_t`). - - - If you are unable to reliably connect to peers: - - You should first read the section on [Connecting and communicating with peers](#connecting-and-communicating-with-peers). - - If the previous step doesn't help move onto our knowledgebase article [Router Config Tips](https://zerotier.atlassian.net/wiki/spaces/SD/pages/6815768/Router+Configuration+Tips). Sometimes this can be a transport-triggered link issue, and sometimes it can be a firewall/NAT issue. - - - API calls seem to fail in nonsensical ways and you're tearing your hair out: - - Be sure to read and understand the [API compatibility with host OS](#api-compatibility-with-host-os) section. - - See the [Debugging](#debugging) section for more advice. - -
- -## API compatibility with host OS - -Since libzt re-implements a socket interface likely very similar to your host OS's own interface it may be tempting to mix and match host OS structures and functions with those of libzt. This may work on occasion, but you are tempting fate. Here are a few important guidelines: - -If you are calling a `zts_*` function, use the appropriate `ZTS_*` constants: -``` -zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) -zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) -``` - -If you are calling a `zts_*` function, use the appropriate `zts_*` structure: -``` -struct zts_sockaddr_in in4; <------ Note the zts_ prefix - ... -zts_bind(fd, (struct sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0) -``` - -If you are calling a host OS function, use your host OS's constants (and structures!): -``` -inet_ntop(AF_INET6, &(in6->sin6_addr), ...); (CORRECT) -inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ...); (INCORRECT) -zts_inet_ntop(ZTS_AF_INET6, &(in6->sin6_addr), ...); (CORRECT) -``` - -If you are calling a host OS function but passing a `zts_*` structure, this can work sometimes but you should take care to pass the correct host OS constants: -``` -struct zts_sockaddr_in6 in6; - ... -inet_ntop(AF_INET6, &(in6->sin6_addr), dstStr, INET6_ADDRSTRLEN); -``` - -
- -## Thread model (advanced) - -Both the **socket** and **control** interfaces are thread-safe but are implemented differently. The socket interface is implemented using a relatively performant core locking mechanism in lwIP. This can be disabled if you know what you're doing. The control interface is implemented by a single coarse-grained lock. This lock is not a performance bottleneck since it only applies to functions that manipulate the ZeroTier service and are called seldomly. Callback events are generated by a separate thread and are independent from the rest of the API's internal locking mechanism. Not returning from a callback event won't impact the rest of the API but it will prevent your application from receiving future events so it is in your application's best interest to perform as little work as possible in the callback function and promptly return control back to ZeroTier. - -*Note: Internally, `libzt` will spawn a number of threads for various purposes: a thread for the core service, a thread for the network stack, a low priority thread to process callback events, and a thread for each network joined. The vast majority of work is performed by the core service and stack threads.* - -
- -## Debugging - -If you're experiencing odd behavior or something that looks like a bug I would suggest first reading and understanding the following sections: - -* [Common pitfalls](#common-pitfalls) -* [API compatibility with host OS](#api-compatibility-with-host-os) -* [Thread model](#thread-model) - -If the information in those sections hasn't helped, there are a couple of ways to get debug traces out of various parts of the library. - -1) Build the library in debug mode with `make host_debug`. This will prevent the stripping of debug symbols from the library and will enable basic output traces from libzt. - -2) If you believe your problem is in the network stack you can manually enable debug traces for individual modules in `src/lwipopts.h`. Toggle the `*_DEBUG` types from `LWIP_DBG_OFF` to `LWIP_DBG_ON`. And then rebuild. This will come with a significant performance cost. - -3) Enabling network stack statistics. This is useful if you want to monitor the stack's receipt and handling of traffic as well as internal things like memory allocations and cache hits. Protocol and service statistics are available in debug builds of `libzt`. These statistics are detailed fully in the section of `include/ZeroTierSockets.h` that is guarded by `LWIP_STATS`. - - ``` - struct zts_stats_proto stats; - if (zts_get_protocol_stats(ZTS_STATS_PROTOCOL_ICMP, &stats) == ZTS_ERR_OK) { - printf("icmp.recv=%d\n", stats.recv); // Count of received pings - } - if (zts_get_protocol_stats(ZTS_STATS_PROTOCOL_TCP, &stats) == ZTS_ERR_OK) { - printf("tcp.drop=%d\n", stats.drop); // Count of dropped TCP packets - } - ``` - -4) There are a series of additional events which can signal whether the network stack or its virtual network interfaces have been set up properly. See `ZTS_EVENT_STACK_*` and `ZTS_EVENT_NETIF_*`. - -
- -## Licensing - -ZeroTier is licensed under the BSL version 1.1. See [LICENSE.txt](./LICENSE.txt) and the ZeroTier pricing page for details. ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license. - -A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](ext/ZeroTierOne/AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). If you want a commercial license to use the ZeroTier SDK in your product contact us directly via [contact@zerotier.com](mailto:contact@zerotier.com) +# Licensing +ZeroTier and the ZeroTier SDK (libzt and libztcore) are licensed under the [BSL version 1.1](./LICENSE.txt). ZeroTier is free to use internally in businesses and academic institutions and for non-commercial purposes. Certain types of commercial use such as building closed-source apps and devices based on ZeroTier or offering ZeroTier network controllers and network management as a SaaS service require a commercial license. A small amount of third party code is also included in ZeroTier and is not subject to our BSL license. See [AUTHORS.md](ext/ZeroTierOne/AUTHORS.md) for a list of third party code, where it is included, and the licenses that apply to it. All of the third party code in ZeroTier is liberally licensed (MIT, BSD, Apache, public domain, etc.). If you want a commercial license to use the ZeroTier SDK in your product contact us directly via [contact@zerotier.com](mailto:contact@zerotier.com) diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..bf59dcc --- /dev/null +++ b/build.ps1 @@ -0,0 +1,206 @@ +function Build-Host +{ + $Arch="x64" + $Artifact="host" + $BuildType="Debug" + $Variant="-DBUILD_HOST=1" + + # Directory for CMake to build and store intermediate files + $env:BuildDir="cache\win-$Arch-$Artifact-"+$BuildType.ToLower() + md $env:BuildDir -ErrorAction:'silentlycontinue' + # Directory where we plan to store the resultant libraries + $env:OutputDir="dist\win-$Arch-$Artifact-"+$BuildType.ToLower() + md $env:OutputDir -ErrorAction:'silentlycontinue' + pushd -Path $env:BuildDir + cmake $Variant -G "Visual Studio 16 2019" -A $Arch ../../ + cmake --build . --config $BuildType + ctest -C debug + popd + # + md $env:OutputDir\lib\ -ErrorAction:'silentlycontinue' + md $env:OutputDir\bin\ -ErrorAction:'silentlycontinue' + cp $env:BuildDir\lib\$BuildType\zt.lib $env:OutputDir\lib\libzt.lib + cp $env:BuildDir\bin\$BuildType\*.exe $env:OutputDir\bin + cp $env:BuildDir\lib\$BuildType\zt-shared.dll $env:OutputDir\lib\libzt.dll + cp $env:BuildDir\lib\$BuildType\zt-shared.pdb $env:OutputDir\lib\libzt.pdb -ErrorAction:'silentlycontinue' + tree /F $env:OutputDir +} + +function Build-Library([string]$BuildType, [string]$Arch, [string]$LangBinding) +{ + $OptLangBinding="" + + if ($LangBinding -eq "csharp") { + $OptLangBinding="-DZTS_ENABLE_PINVOKE=1" + $LangBindingPostfix="pinvoke" + } + if ($LangBinding -eq "java") { + $OptLangBinding="-DZTS_ENABLE_JAVA=1" + $LangBindingPostfix="jni" + } + + $archAlias = "" + $bitCount = "" + + if ($Arch -eq "Win32") { + $bitCount="32" + $archAlias="win-x86" + } + if ($Arch -eq "x64") { + $bitCount="64" + $archAlias="win-x64" + } + #if ($Arch -eq "ARM32") { + # $bitCount="32" + # $archAlias="win-arm" + #} + if ($Arch -eq "ARM") { + $bitCount="64" + $archAlias="win-arm64" + } + + if ($archAlias -eq "" -or $bitCount -eq "") { + echo "No valid architecture specified. Breaking." + break + } + + # Directory for CMake to build and store intermediate files + $env:BuildDir="cache\win-$Arch-$LangBindingPostfix-"+$BuildType.ToLower() + md $env:BuildDir -ErrorAction:'silentlycontinue' + # Directory where we plan to store the resultant libraries + $env:OutputDir="dist\win-$Arch-$LangBindingPostfix-"+$BuildType.ToLower() + md $env:OutputDir -ErrorAction:'silentlycontinue' + pushd -Path $env:BuildDir + cmake ${OptLangBinding} -G "Visual Studio 16 2019" -A $Arch ../../ + cmake --build . --config $BuildType + popd + md $env:OutputDir\lib\ -ErrorAction:'silentlycontinue' + #cp $env:BuildDir\$BuildType\zt.lib $env:OutputDir\lib\libzt.lib + cp $env:BuildDir\$BuildType\zt-shared.dll $env:OutputDir\lib\libzt.dll + cp $env:BuildDir\$BuildType\zt-shared.pdb $env:OutputDir\lib\libzt.pdb -ErrorAction:'silentlycontinue' +} + +function Build-All +{ + # Win32 + Build-Library -BuildType "Release" -Arch "Win32" -LangBinding "" + Build-Library -BuildType "Release" -Arch "Win32" -LangBinding "csharp" + Build-Library -BuildType "Debug" -Arch "Win32" -LangBinding "" + Build-Library -BuildType "Debug" -Arch "Win32" -LangBinding "csharp" + # x64 + Build-Library -BuildType "Release" -Arch "x64" -LangBinding "" + Build-Library -BuildType "Release" -Arch "x64" -LangBinding "csharp" + Build-Library -BuildType "Debug" -Arch "x64" -LangBinding "" + Build-Library -BuildType "Debug" -Arch "x64" -LangBinding "csharp" +} + +function BuildNuGetPackages([string]$Version) +{ + BuildNuGetPackage-Sockets -BuildType "Release" -Arch "x64" -Version $Version + BuildNuGetPackage-Sockets -BuildType "Debug" -Arch "x64" -Version $Version + BuildNuGetPackage-Sockets -BuildType "Release" -Arch "Win32" -Version $Version + BuildNuGetPackage-Sockets -BuildType "Debug" -Arch "Win32" -Version $Version +} + +function BuildNuGetPackage-Sockets([string]$BuildType, [string]$Arch, [string]$Version) +{ + $archAlias = $Arch + if ($Arch -eq "Win32") { + $archAlias="x86" + } + + $TargetTuple = "win-"+$archAlias+"-nuget-"+$($BuildType.ToLower()) + + # Where we plan to output *.nupkg(s) + md pkg\nuget\ZeroTier.Sockets\bin\ -Force + md dist\$TargetTuple -Force + del dist\$TargetTuple\*.nupkg -ErrorAction:'silentlycontinue' + + # licenses + md pkg\nuget\ZeroTier.Sockets\licenses -Force + cp LICENSE.txt pkg\nuget\ZeroTier.Sockets\licenses + + # contentFiles (sources) + md pkg\nuget\ZeroTier.Sockets\contentFiles -Force + cp src\bindings\csharp\*.cs pkg\nuget\ZeroTier.Sockets\contentFiles + cp examples\csharp\*.cs pkg\nuget\ZeroTier.Sockets\contentFiles + + # runtimes + md pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\native -Force + md pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0 -Force + #md pkg\nuget\ZeroTier.Sockets\runtimes\win10-arm\native -Force + + # Build wrapper library for C# ZeroTier.Sockets abstraction + csc -target:library -debug:pdbonly ` + -pdb:pkg\nuget\ZeroTier.Sockets\bin\ZeroTier.Sockets.pdb ` + -out:pkg\nuget\ZeroTier.Sockets\bin\ZeroTier.Sockets.dll ` + .\src\bindings\csharp\*.cs + + # Build unmanaged native libzt.dll with exported P/INVOKE symbols + Build-Library -BuildType $BuildType -Arch $Arch -LangBinding "csharp" + + # Copy native libzt.dll into package tree + cp .\dist\win-$archAlias-pinvoke-$($BuildType.ToLower())\lib\*.dll ` + pkg\nuget\ZeroTier.Sockets\bin\libzt.dll + + # .NET Framework + md pkg\nuget\ZeroTier.Sockets\lib\net40 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net403 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net45 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net451 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net452 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net46 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net461 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net462 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net47 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net471 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net472 -Force + md pkg\nuget\ZeroTier.Sockets\lib\net48 -Force + + # .NET "Core" 5.0 (moniker missing from microsoft documentation?) + md pkg\nuget\ZeroTier.Sockets\lib\net5.0 -Force + + # Copy assemblies into framework-specific directories. + $folders = Get-ChildItem pkg\nuget\ZeroTier.Sockets\lib\ + foreach ($folder in $folders.name){ + cp -Path "pkg\nuget\ZeroTier.Sockets\bin\*.*" ` + -Destination "pkg\nuget\ZeroTier.Sockets\lib\$folder" -Recurse + } + + # Native DLL placement + + cp .\dist\win-$archAlias-pinvoke-$($BuildType.ToLower())\lib\*.dll ` + pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0\libzt.dll + cp .\dist\win-$archAlias-pinvoke-$($BuildType.ToLower())\lib\*.dll ` + pkg\nuget\ZeroTier.Sockets\lib\net40\libzt.dll + cp .\dist\win-$archAlias-pinvoke-$($BuildType.ToLower())\lib\*.dll ` + pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\native\libzt.dll + cp .\dist\win-$archAlias-pinvoke-$($BuildType.ToLower())\lib\*.pdb ` + pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0\libzt.pdb + + # Package + pushd -Path pkg\nuget\ZeroTier.Sockets + nuget pack ZeroTier.Sockets.$archAlias.nuspec ` + -Version $Version -OutputDirectory ..\..\..\dist\$TargetTuple\ + popd +} + +function Clean-PackageDirectory +{ + rm pkg\nuget\ZeroTier.Sockets\lib ` + -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' + rm pkg\nuget\ZeroTier.Sockets\contentFiles ` + -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' + rm pkg\nuget\ZeroTier.Sockets\licenses ` + -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' + rm pkg\nuget\ZeroTier.Sockets\runtimes ` + -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' + rm pkg\nuget\ZeroTier.Sockets\bin ` + -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' +} + +function Clean +{ + rm cache -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' + rm dist -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' +} diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5c3ab3b --- /dev/null +++ b/build.sh @@ -0,0 +1,543 @@ +#!/bin/bash + +# ----------------------------------------------------------------------------- +# | SYSTEM DISCOVERY AND CONFIGURATION | +# ----------------------------------------------------------------------------- + +# Find and set cmake +CMAKE=cmake3 +if [[ $(which $CMAKE) = "" ]]; +then + CMAKE=cmake # try this next +fi +if [[ $(which $CMAKE) = "" ]]; +then + echo "CMake (cmake) not found. Please install before continuing." + exit +fi + +# +if [[ ! $(which tree) = "" ]]; +then + TREE=tree +else + TREE="du -a " +fi + +# Determine operating system +OSNAME=$(uname | tr '[A-Z]' '[a-z]') +if [[ $OSNAME = *"darwin"* ]]; then + SHARED_LIB_NAME="libzt.dylib" + STATIC_LIB_NAME="libzt.a" + HOST_PLATFORM="macos" +fi +if [[ $OSNAME = *"linux"* ]]; then + SHARED_LIB_NAME="libzt.so" + STATIC_LIB_NAME="libzt.a" + HOST_PLATFORM="linux" +fi + +# Determine and normalize machine type +HOST_MACHINE_TYPE=$(uname -m) +if [[ $HOST_MACHINE_TYPE = *"x86_64"* ]]; then + HOST_MACHINE_TYPE="x64" +fi + +# Determine number of cores. We'll tell CMake to use them all +if [[ $OSNAME = *"darwin"* ]]; then + N_PROCESSORS=$(sysctl -n hw.ncpu) +fi +if [[ $OSNAME = *"linux"* ]]; then + N_PROCESSORS=$(nproc --all) +fi + +# How many processor cores CMake should use during builds, +# comment out the below line out if you don't want parallelism: +BUILD_CONCURRENCY="-j $N_PROCESSORS" + +# ----------------------------------------------------------------------------- +# | PATHS | +# ----------------------------------------------------------------------------- + +# Where we place all finished artifacts +BUILD_OUTPUT_DIR=$(pwd)/dist +# Where we tell CMake to place its build systems and their caches +BUILD_CACHE_DIR=$(pwd)/cache +# Where package projects, scripts, spec files, etc live +PKG_DIR=$(pwd)/pkg +# Default location for (host) libraries +DEFAULT_HOST_LIB_OUTPUT_DIR=$BUILD_OUTPUT_DIR/$HOST_PLATFORM-$HOST_MACHINE_TYPE +# Default location for (host) binaries +DEFAULT_HOST_BIN_OUTPUT_DIR=$BUILD_OUTPUT_DIR/$HOST_PLATFORM-$HOST_MACHINE_TYPE +# Default location for (host) packages +DEFAULT_HOST_PKG_OUTPUT_DIR=$BUILD_OUTPUT_DIR/$HOST_PLATFORM-$HOST_MACHINE_TYPE +# Defaultlocation for CMake's caches (when building for host) +DEFAULT_HOST_BUILD_CACHE_DIR=$BUILD_CACHE_DIR/$HOST_PLATFORM-$HOST_MACHINE_TYPE + +gethosttype() +{ + echo $HOST_PLATFORM-$HOST_MACHINE_TYPE +} + +# ----------------------------------------------------------------------------- +# | TARGETS | +# ----------------------------------------------------------------------------- + +# Build xcframework +# +# ./build.sh xcframework "debug" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/apple-xcframework-debug +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# apple-xcframework-debug +# └── pkg +# └── zt.xcframework +# ├── Info.plist +# ├── ios-arm64 +# │   └── zt.framework +# │   └── ... +# ├── ios-arm64_x86_64-simulator +# │   └── zt.framework +# │   └── ... +# └── macos-arm64_x86_64 +# └── zt.framework +# └── ... +# +xcframework() +{ + if [[ ! $OSNAME = *"darwin"* ]]; then + echo "Can only build this on a Mac" + exit 0 + fi + BUILD_TYPE=${1:-release} + UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}" + + # Build all frameworks + macos-framework $BUILD_TYPE + iphoneos-framework $BUILD_TYPE + iphonesimulator-framework $BUILD_TYPE + + ARTIFACT="xcframework" + TARGET_PLATFORM="apple" + TARGET_BUILD_DIR=$BUILD_OUTPUT_DIR/$TARGET_PLATFORM-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg + mkdir -p $PKG_OUTPUT_DIR + + MACOS_FRAMEWORK_DIR=macos-x64-framework-$BUILD_TYPE + IOS_FRAMEWORK_DIR=iphoneos-arm64-framework-$BUILD_TYPE + IOS_SIM_FRAMEWORK_DIR=iphonesimulator-x64-framework-$BUILD_TYPE + + # Pack everything + rm -rf $PKG_OUTPUT_DIR/zt.xcframework # Remove prior to move to prevent error + xcodebuild -create-xcframework \ + -framework $BUILD_CACHE_DIR/$MACOS_FRAMEWORK_DIR/lib/$UPPERCASE_BUILD_TYPE/zt.framework \ + -framework $BUILD_CACHE_DIR/$IOS_FRAMEWORK_DIR/lib/$UPPERCASE_BUILD_TYPE/zt.framework \ + -framework $BUILD_CACHE_DIR/$IOS_SIM_FRAMEWORK_DIR/lib/$UPPERCASE_BUILD_TYPE/zt.framework \ + -output $PKG_OUTPUT_DIR/zt.xcframework +} + +# Build iOS framework +# +# ./build.sh iphonesimulator-framework "debug" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/iphonesimulator-x64-framework-debug +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# /Volumes/$USER/zt/libzt/libzt-dev/dist/iphonesimulator-x64-framework-debug +# └── pkg +# └── zt.framework +# ├── Headers +# │   └── ZeroTierSockets.h +# ├── Info.plist +# ├── Modules +# │   └── module.modulemap +# └── zt +# +iphonesimulator-framework() +{ + if [[ ! $OSNAME = *"darwin"* ]]; then + echo "Can only build this on a Mac" + exit 0 + fi + ARTIFACT="framework" + BUILD_TYPE=${1:-Release} + UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}" + VARIANT="-DBUILD_IOS_FRAMEWORK=True" + TARGET_PLATFORM="iphonesimulator" + TARGET_MACHINE_TYPE="x64" # presumably + CACHE_DIR=$BUILD_CACHE_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$BUILD_OUTPUT_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg + mkdir -p $PKG_OUTPUT_DIR + # Generate project + mkdir -p $CACHE_DIR + cd $CACHE_DIR + # iOS (SDK 11+, 64-bit only, arm64) + $CMAKE -G Xcode ../../ $VARIANT + # Build framework + xcodebuild -target zt -configuration "$UPPERCASE_BUILD_TYPE" -sdk "iphonesimulator" + cd - + cp -rf $CACHE_DIR/lib/$UPPERCASE_BUILD_TYPE/*.framework $PKG_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + +# Build macOS framework +# +# ./build.sh macos-framework "debug" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/macos-x64-framework-debug +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# /Volumes/$USER/zt/libzt/libzt-dev/dist/macos-x64-framework-debug +# └── pkg +# └── zt.framework +# ├── Headers +# │   └── ZeroTierSockets.h +# ├── Info.plist +# ├── Modules +# │   └── module.modulemap +# └── zt +# +macos-framework() +{ + if [[ ! $OSNAME = *"darwin"* ]]; then + echo "Can only build this on a Mac" + exit 0 + fi + ARTIFACT="framework" + BUILD_TYPE=${1:-Release} + UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}" + VARIANT="-DBUILD_MACOS_FRAMEWORK=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg + mkdir -p $PKG_OUTPUT_DIR + # Generate project + mkdir -p $CACHE_DIR + cd $CACHE_DIR + $CMAKE -G Xcode ../../ $VARIANT + # Build framework + xcodebuild -target zt -configuration $UPPERCASE_BUILD_TYPE -sdk "macosx" + cd - + cp -rf $CACHE_DIR/lib/$UPPERCASE_BUILD_TYPE/*.framework $PKG_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + +# Build iOS framework +# +# ./build.sh iphoneos-framework "debug" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/iphoneos-arm64-framework-debug +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# /Volumes/$USER/zt/libzt/libzt-dev/dist/iphoneos-arm64-framework-debug +# └── pkg +# └── zt.framework +# ├── Headers +# │   └── ZeroTierSockets.h +# ├── Info.plist +# ├── Modules +# │   └── module.modulemap +# └── zt +# +iphoneos-framework() +{ + if [[ ! $OSNAME = *"darwin"* ]]; then + echo "Can only build this on a Mac" + exit 0 + fi + ARTIFACT="framework" + BUILD_TYPE=${1:-Release} + UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}" + VARIANT="-DBUILD_IOS_FRAMEWORK=True -DIOS_ARM64=True" + TARGET_PLATFORM="iphoneos" + TARGET_MACHINE_TYPE=arm64 + CACHE_DIR=$BUILD_CACHE_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$BUILD_OUTPUT_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg + mkdir -p $PKG_OUTPUT_DIR + # Generate project + mkdir -p $CACHE_DIR + cd $CACHE_DIR + # iOS (SDK 11+, 64-bit only, arm64) + $CMAKE -G Xcode ../../ $VARIANT + sed -i '' 's/x86_64/$(CURRENT_ARCH)/g' zt.xcodeproj/project.pbxproj + # Build framework + xcodebuild -arch $TARGET_MACHINE_TYPE -target zt -configuration "$UPPERCASE_BUILD_TYPE" -sdk "iphoneos" + cd - + cp -rvf $CACHE_DIR/lib/$UPPERCASE_BUILD_TYPE/*.framework $PKG_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + +# Build standard libraries, examples, and selftest +# +# ./build.sh host "release" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/linux-x64-host-release +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# linux-x64-host-release +# ├── bin +# │   ├── client +# │   └── server +# └── lib +#  ├── libzt.a +#  └── libzt.so # .dylib, .dll +# +host() +{ + ARTIFACT="host" + # Default to release + BUILD_TYPE=${1:-release} + VARIANT="-DBUILD_HOST=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib + BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin + mkdir -p $LIB_OUTPUT_DIR + mkdir -p $BIN_OUTPUT_DIR + $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE + $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + cp -f $CACHE_DIR/lib/libzt.* $LIB_OUTPUT_DIR + cp -f $CACHE_DIR/bin/* $BIN_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} +host-install() +{ + cd cache/$HOST_PLATFORM-$HOST_MACHINE_TYPE-host-$1/ + make install + cd - +} +host-uninstall() +{ + cd cache/$HOST_PLATFORM-$HOST_MACHINE_TYPE-host-$1/ + xargs rm < install_manifest.txt + cd - +} + +# Build shared library with python wrapper symbols exported +host-python() +{ + ARTIFACT="python" + # Default to release + BUILD_TYPE=${1:-release} + VARIANT="-DZTS_ENABLE_PYTHON=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib + BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin + mkdir -p $LIB_OUTPUT_DIR + # Optional step to generate new SWIG wrapper + swig -c++ -python -o src/bindings/python/zt_wrap.cpp -Iinclude src/bindings/python/zt.i + $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE + $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + cp -f $CACHE_DIR/lib/$SHARED_LIB_NAME $LIB_OUTPUT_DIR/_libzt.so + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + +# Build shared library with P/INVOKE wrapper symbols exported +host-pinvoke() +{ + ARTIFACT="pinvoke" + # Default to release + BUILD_TYPE=${1:-release} + VARIANT="-DZTS_ENABLE_PINVOKE=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib + BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin + mkdir -p $LIB_OUTPUT_DIR + $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE + $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + cp -f $CACHE_DIR/lib/libzt.* $LIB_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + +# Build shared library with Java JNI wrapper symbols exported (.jar) +host-jar() +{ + ARTIFACT="jar" + # Default to release + BUILD_TYPE=${1:-release} + VARIANT="-DZTS_ENABLE_JAVA=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + PKG_OUTPUT_DIR=$TARGET_BUILD_DIR/pkg + mkdir -p $PKG_OUTPUT_DIR + # Share same cache dir with CMake + JAVA_JAR_DIR=$CACHE_DIR/pkg/jar + JAVA_JAR_SOURCE_TREE_DIR=$JAVA_JAR_DIR/com/zerotier/libzt/ + mkdir -p $JAVA_JAR_SOURCE_TREE_DIR + cp -f src/bindings/java/*.java $JAVA_JAR_SOURCE_TREE_DIR + # Build + $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE + $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + # Package everything + cp -f $CACHE_DIR/lib/libzt.* $JAVA_JAR_DIR + cd $JAVA_JAR_DIR + export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 + javac com/zerotier/libzt/*.java + jar cf libzt-"$(git describe --abbrev=0)".jar $SHARED_LIB_NAME com/zerotier/libzt/*.class + rm -rf com $SHARED_LIB_NAME + cd - + # Copy JAR to dist/ + echo -e "\nContents of JAR:\n" + jar tf $JAVA_JAR_DIR/*.jar + echo -e + mv $JAVA_JAR_DIR/*.jar $PKG_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR +} + + +# ----------------------------------------------------------------------------- +# | ANDROID CONFIG | +# ----------------------------------------------------------------------------- + +ANDROID_PKG_PROJ_DIR=$(pwd)/pkg/android + +# Set ANDROID_HOME because setting sdk.dir in local.properties isn't always reliable +#export PATH=/Library/Java/JavaVirtualMachines/$JDK/Contents/Home/bin/:${PATH} +#export PATH=/Users/$USER/Library/Android/sdk/platform-tools/:${PATH} +GRADLE_ARGS=--stacktrace +#ANDROID_APP_NAME=com.example.mynewestapplication +# for our purposes we limit this to execution on macOS +if [[ $OSNAME = *"linux"* ]]; then + export ANDROID_HOME=/usr/lib/android-sdk/ +fi +if [[ $OSNAME = *"darwin"* ]]; then + export ANDROID_HOME=/Users/$USER/Library/Android/sdk +fi + +# Build shared library with Java JNI wrapper symbols exported (.aar) +# +# ./build.sh android-aar "release" +# +# Example output: +# +# - Cache : /Volumes/$USER/zt/libzt/libzt-dev/cache/android-any-android-release +# - Build output : /Volumes/$USER/zt/libzt/libzt-dev/dist +# +# android-any-android-release +# └── libzt-release.aar +# +android-aar() +{ + ARTIFACT="android" + BUILD_TYPE=${1:-release} # Default to release + CMAKE_SWITCH="ZTS_ENABLE_JAVA" + TARGET_PLATFORM="android" + TARGET_MACHINE_TYPE=any + CACHE_DIR=$BUILD_CACHE_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + PKG_OUTPUT_DIR=$BUILD_OUTPUT_DIR/$TARGET_PLATFORM-$TARGET_MACHINE_TYPE-$ARTIFACT-$BUILD_TYPE + mkdir -p $CACHE_DIR + mkdir -p $PKG_OUTPUT_DIR + # Unsure why, but Gradle's build script chokes on this non-source file now + rm -rf ext/ZeroTierOne/ext/miniupnpc/VERSION + export PATH=$ANDROID_HOME/cmdline-tools/tools/bin:$PATH + # Copy source files into project + cp -f src/bindings/java/*.java ${ANDROID_PKG_PROJ_DIR}/app/src/main/java/com/zerotier/libzt + # Build + UPPERCASE_BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}" + CMAKE_FLAGS="-D${CMAKE_SWITCH}=1 -D${CMAKE_SWITCH}=ON" + cd $ANDROID_PKG_PROJ_DIR + ./gradlew $GRADLE_ARGS assemble$UPPERCASE_BUILD_TYPE # assembleRelease / assembleDebug + mv $ANDROID_PKG_PROJ_DIR/app/build/outputs/aar/*.aar \ + $PKG_OUTPUT_DIR/libzt-$BUILD_TYPE.aar + cd - + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $PKG_OUTPUT_DIR +} + +# Build static library and selftest. Currently this only tests +# the core C API, not any of the language bindings. +test() +{ + ARTIFACT="test" + # Default to release + BUILD_TYPE=${1:-release} + VARIANT="-DBUILD_HOST_SELFTEST_ONLY=True" + CACHE_DIR=$DEFAULT_HOST_BUILD_CACHE_DIR-$ARTIFACT-$BUILD_TYPE + TARGET_BUILD_DIR=$DEFAULT_HOST_BIN_OUTPUT_DIR-$ARTIFACT-$BUILD_TYPE + rm -rf $TARGET_BUILD_DIR + LIB_OUTPUT_DIR=$TARGET_BUILD_DIR/lib + BIN_OUTPUT_DIR=$TARGET_BUILD_DIR/bin + mkdir -p $BIN_OUTPUT_DIR + $CMAKE $VARIANT -H. -B$CACHE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE + $CMAKE --build $CACHE_DIR $BUILD_CONCURRENCY + cp -f $CACHE_DIR/bin/* $BIN_OUTPUT_DIR + echo -e "\n - Build cache : $CACHE_DIR\n - Build output : $BUILD_OUTPUT_DIR\n" + $TREE $TARGET_BUILD_DIR + # Test + cd $CACHE_DIR + ctest -C release + cd - +} + +# Recursive deep clean +clean() +{ + # Finished artifacts + rm -rf $BUILD_OUTPUT_DIR + # CMake's build system cache + rm -rf $BUILD_CACHE_DIR + # CMake test output + rm -rf Testing + # Android AAR project binaries and sources (copied from src/bindings/java) + rm -rf $ANDROID_PKG_PROJ_DIR/app/build + rm -rf $ANDROID_PKG_PROJ_DIR/app/src/main/java/com/zerotier/libzt/*.java + rm -rf $ANDROID_PKG_PROJ_DIR/app/.externalNativeBuild + # Remove whatever remains + find . \ + \( -name '*.dylib' \ + -o -name '*.dll' \ + -o -name '*.aar' \ + -o -name '*.jar' \ + -o -name '*.so' \ + -o -name '*.a' \ + -o -name '*.o' \ + -o -name '*.exe' \ + -o -name '*.o.d' \ + -o -name '*.out' \ + -o -name '*.log' \ + -o -name '*.dSYM' \ + -o -name '*.class' \ + \) -exec rm -rf {} + + + find . -type d -name "__pycache__" -exec rm -rf {} + +} + +list() +{ + IFS=$'\n' + for f in $(declare -F); do + echo "${f:11}" + done +} + +"$@" diff --git a/dist.ps1 b/dist.ps1 deleted file mode 100644 index ff3c440..0000000 --- a/dist.ps1 +++ /dev/null @@ -1,175 +0,0 @@ -function Clean -{ - Remove-Item builds -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item tmp -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item lib -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item bin -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - # pkg - Clean-PackageDirectory - Get-ChildItem pkg -recurse -include *.dll | remove-item - Get-ChildItem pkg -recurse -include *.lib | remove-item - Get-ChildItem pkg -recurse -include *.pdb | remove-item - Get-ChildItem pkg -recurse -include *.nupkg | remove-item - # src - Get-ChildItem src -recurse -include *.dll | remove-item - Get-ChildItem src -recurse -include *.lib | remove-item - Get-ChildItem src -recurse -include *.pdb | remove-item - Get-ChildItem src -recurse -include *.dylib | remove-item - Get-ChildItem src -recurse -include *.so | remove-item - Get-ChildItem src -recurse -include *.exe | remove-item - Get-ChildItem src -recurse -include *.out | remove-item - Get-ChildItem src -recurse -include *.a | remove-item -} - -function Build-Library([string]$BuildType, [string]$Arch, [string]$LanguageBinding) -{ - $OptionalLanguageBinding="" - - if ($LanguageBinding -eq "csharp") { - $OptionalLanguageBinding="-DZTS_PINVOKE:BOOL=ON" - $LanguageBindingPostfix="-pinvoke" - } - if ($LanguageBinding -eq "java") { - #$OptionalLanguageBinding="-DSDK_JNI=ON -DSDK_JNI=1" - #$LanguageBindingPostfix="-jni" - } - - $archAlias = "" - $bitCount = "" - - if ($Arch -eq "Win32") { - $bitCount="32" - $archAlias="win-x86" - } - if ($Arch -eq "x64") { - $bitCount="64" - $archAlias="win-x64" - } - #if ($Arch -eq "ARM32") { - # $bitCount="32" - # $archAlias="win-arm" - #} - if ($Arch -eq "ARM") { - $bitCount="64" - $archAlias="win-arm64" - } - - if ($archAlias -eq "" -or $bitCount -eq "") { - echo "No valid architecture specified. Breaking." - break - } - - # Directory for CMake to build and store intermediate files - $env:BuildDir="tmp\$BuildType\"+$Arch+$LanguageBindingPostfix - md $env:BuildDir -ErrorAction:'silentlycontinue' - # Directory where we plan to store the resultant libraries - $env:OutputDir="lib\"+$BuildType.ToLower() - md $env:OutputDir\$archAlias$LanguageBindingPostfix -ErrorAction:'silentlycontinue' - Push-Location -Path $env:BuildDir - cmake ${OptionalLanguageBinding} -G "Visual Studio 16 2019" -A $Arch ../../../ - cmake --build . --config $BuildType - Pop-Location - Copy-Item $env:BuildDir\$BuildType\zt.lib $env:OutputDir\$archAlias$LanguageBindingPostfix\libzt$bitCount.lib - Copy-Item $env:BuildDir\$BuildType\zt-shared.dll $env:OutputDir\$archAlias$LanguageBindingPostfix\libzt$bitCount.dll - Copy-Item $env:BuildDir\$BuildType\zt-shared.pdb $env:OutputDir\$archAlias$LanguageBindingPostfix\libzt$bitCount.pdb -ErrorAction:'silentlycontinue' -} - -function Build-All -{ - # Win32 - Build-Library -BuildType "Release" -Arch "Win32" -LanguageBinding "" - Build-Library -BuildType "Release" -Arch "Win32" -LanguageBinding "pinvoke" - Build-Library -BuildType "Debug" -Arch "Win32" -LanguageBinding "" - Build-Library -BuildType "Debug" -Arch "Win32" -LanguageBinding "pinvoke" - # x64 - Build-Library -BuildType "Release" -Arch "x64" -LanguageBinding "" - Build-Library -BuildType "Release" -Arch "x64" -LanguageBinding "pinvoke" - Build-Library -BuildType "Debug" -Arch "x64" -LanguageBinding "" - Build-Library -BuildType "Debug" -Arch "x64" -LanguageBinding "pinvoke" -} - -function BuildNuGetPackages([string]$Version) -{ - BuildNuGetPackage-Sockets -BuildType "Release" -Arch "x64" -Version $Version - BuildNuGetPackage-Sockets -BuildType "Debug" -Arch "x64" -Version $Version - BuildNuGetPackage-Sockets -BuildType "Release" -Arch "Win32" -Version $Version - BuildNuGetPackage-Sockets -BuildType "Debug" -Arch "Win32" -Version $Version -} - -function BuildNuGetPackage-Sockets([string]$BuildType, [string]$Arch, [string]$Version) -{ - $archAlias = $Arch - if ($Arch -eq "Win32") { - $archAlias="x86" - } - - md pkg\nuget\ZeroTier.Sockets\bin\ -Force - md builds\pkg\nuget\$($BuildType.ToLower())\$archAlias -Force - del builds\pkg\nuget\$($BuildType.ToLower())\$archAlias\*.nupkg -ErrorAction:'silentlycontinue' - - # licenses - md pkg\nuget\ZeroTier.Sockets\licenses -Force - Copy-Item LICENSE.txt pkg\nuget\ZeroTier.Sockets\licenses - - # contentFiles (sources) - md pkg\nuget\ZeroTier.Sockets\contentFiles -Force - Copy-Item src\bindings\csharp\*.cs pkg\nuget\ZeroTier.Sockets\contentFiles - - # Where we plan to output *.nupkg(s) - md builds\pkg\nuget\$($BuildType.ToLower()) -Force - - # runtimes - md pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\native -Force - md pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0 -Force - #md pkg\nuget\ZeroTier.Sockets\runtimes\win10-arm\native -Force - - # Build wrapper library for C# ZeroTier.Sockets abstraction - csc -target:library -debug:pdbonly -pdb:pkg\nuget\ZeroTier.Sockets\bin\ZeroTier.Sockets.pdb -out:pkg\nuget\ZeroTier.Sockets\bin\ZeroTier.Sockets.dll .\src\bindings\csharp\*.cs - - # Build unmanaged native libzt.dll with exported P/INVOKE symbols - Build-Library -BuildType $BuildType -Arch $Arch -LanguageBinding "csharp" - Copy-Item .\lib\$($BuildType.ToLower())\win-$archAlias-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\bin\libzt.dll - - # .NET Framework - md pkg\nuget\ZeroTier.Sockets\lib\net40 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net403 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net45 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net451 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net452 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net46 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net461 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net462 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net47 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net471 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net472 -Force - md pkg\nuget\ZeroTier.Sockets\lib\net48 -Force - - # .NET "Core" 5.0 (moniker missing from microsoft documentation?) - md pkg\nuget\ZeroTier.Sockets\lib\net5.0 -Force - - # Copy assemblies into framework-specific directories. - $folders = Get-ChildItem pkg\nuget\ZeroTier.Sockets\lib\ - foreach ($folder in $folders.name){ - Copy-Item -Path "pkg\nuget\ZeroTier.Sockets\bin\*.*" -Destination "pkg\nuget\ZeroTier.Sockets\lib\$folder" -Recurse - } - - # Native DLL placement - Copy-Item .\lib\$($BuildType.ToLower())\win-$archAlias-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0\libzt.dll - Copy-Item .\lib\$($BuildType.ToLower())\win-$archAlias-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\lib\net40\libzt.dll - Copy-Item .\lib\$($BuildType.ToLower())\win-$archAlias-pinvoke\*.dll pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\native\libzt.dll - Copy-Item .\lib\$($BuildType.ToLower())\win-$archAlias-pinvoke\*.pdb pkg\nuget\ZeroTier.Sockets\runtimes\win10-$archAlias\lib\uap10.0\libzt.pdb - - # Package - Push-Location -Path pkg\nuget\ZeroTier.Sockets - nuget pack ZeroTier.Sockets.$archAlias.nuspec -Version $Version -OutputDirectory ..\..\..\builds\pkg\nuget\$($BuildType.ToLower())\$archAlias - Pop-Location -} - -function Clean-PackageDirectory -{ - Remove-Item pkg\nuget\ZeroTier.Sockets\lib -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item pkg\nuget\ZeroTier.Sockets\contentFiles -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item pkg\nuget\ZeroTier.Sockets\licenses -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item pkg\nuget\ZeroTier.Sockets\runtimes -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' - Remove-Item pkg\nuget\ZeroTier.Sockets\bin -Recurse -Force -Confirm:$false -ErrorAction:'silentlycontinue' -} diff --git a/dist.sh b/dist.sh deleted file mode 100755 index 97b0c40..0000000 --- a/dist.sh +++ /dev/null @@ -1,737 +0,0 @@ -#!/bin/bash - -# This script works in conjunction with the Makefile and CMakeLists.txt. It is -# intended to be called from the Makefile, it generates projects and builds -# targets as specified in CMakeLists.txt. In addition, this script is -# responsible for packaging all of the resultant builds, licenses, and -# documentation as well as controlling the installation and remote execution of -# tests on mobile devices. - -# Example workflow for producing a full release package: -# -# (1) On packaging platform, build most targets (including android and ios): -# (1a) make all -# (1b) make wrap -# (2) On other supported platforms, build remaining supported targets -# and copy them into a directory structure that is expected by a later stage: -# (2a) make all -# (2b) make wrap -# (3) Copy all resultant $(ARCH)_product directories to root project directory -# of packaging platform. For instance: -# -# libzt -# ├── README.md -# ├── products -# ├── linux-x86_64_products -# ├── linux-armv7l_products -# ├── linux-armv6l_products -# ├── products -# ├── win_products -# └── ... -# -# (4) Merge all builds into single `products` directory and package: -# (4a) make clean -# (4a) make dist - -CMAKE=cmake -BUILD_CONCURRENCY= -#"-j 2" -OSNAME=$(uname | tr '[A-Z]' '[a-z]') -BUILD_TMP=$(pwd)/tmp -ANDROID_PROJ_DIR=$(pwd)/pkg/android -XCODE_IOS_PROJ_DIR=$(pwd)/ports/xcode_ios -XCODE_IOS_SIMULATOR_PROJ_DIR=$(pwd)/ports/xcode_ios_simulator -XCODE_MACOS_PROJ_DIR=$(pwd)/ports/xcode_macos - -# Generates wrapper source files for various target languages -generate_swig_wrappers() -{ - SRC=../src - - cd ports/; - - # C# - mkdir -p ${SRC}/csharp - swig -csharp -c++ zt.i - # Prepend our callback garb to libzt.cs, copy new source files into src/csharp - cat csharp/csharp_callback.cs libzt.cs > libzt_concat.cs - rm libzt.cs - mv libzt_concat.cs libzt.cs - mv -f *.cs zt_wrap.cxx ${SRC}/csharp/ - - # Javascript - # Build for all three engines. Why not? - ENGINE=jsc - mkdir -p ${SRC}/js/${ENGINE} - swig -javascript -${ENGINE} -c++ zt.i - mv zt_wrap.cxx ${SRC}/js/${ENGINE} - ENGINE=v8 - mkdir -p ${SRC}/js/${ENGINE} - swig -javascript -${ENGINE} -c++ zt.i - mv zt_wrap.cxx ${SRC}/js/${ENGINE} - ENGINE=node - mkdir -p ${SRC}/js/${ENGINE} - swig -javascript -${ENGINE} -c++ zt.i - mv -f zt_wrap.cxx ${SRC}/js/${ENGINE} - - # Python - mkdir -p ${SRC}/python - swig -python -c++ zt.i - mv -f zt_wrap.cxx *.py ${SRC}/python - - # Lua - mkdir -p ${SRC}/lua - swig -lua -c++ zt.i - mv -f zt_wrap.cxx ${SRC}/lua - - # Go 64 - mkdir -p ${SRC}/go64 - swig -intgosize 64 -go -c++ zt.i - mv -f zt_wrap.cxx *.go *.c ${SRC}/go64 - - # Go 32 - mkdir -p ${SRC}/go32 - swig -intgosize 32 -go -c++ zt.i - mv -f zt_wrap.cxx *.go *.c ${SRC}/go32 - - cd - -} - -# Generates projects if needed -generate_projects() -{ - if [[ ! $OSNAME = *"darwin"* ]]; then - exit 0 - fi - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - if [[ $OSNAME = *"darwin"* ]]; then - # iOS (SDK 11+, 64-bit only, arm64) - if [ ! -d "$XCODE_IOS_PROJ_DIR" ]; then - mkdir -p $XCODE_IOS_PROJ_DIR - cd $XCODE_IOS_PROJ_DIR - $CMAKE -G Xcode ../../ -DIOS_FRAMEWORK=1 -DIOS_ARM64=1 - # Manually replace arch strings in project file - sed -i '' 's/x86_64/$(CURRENT_ARCH)/g' zt.xcodeproj/project.pbxproj - cd - - fi - - if [ ! -d "$XCODE_IOS_SIMULATOR_PROJ_DIR" ]; then - mkdir -p $XCODE_IOS_SIMULATOR_PROJ_DIR - cd $XCODE_IOS_SIMULATOR_PROJ_DIR - $CMAKE -G Xcode ../../ -DIOS_FRAMEWORK=1 - # Manually replace arch strings in project file - #sed -i '' 's/x86_64/$(CURRENT_ARCH)/g' zt.xcodeproj/project.pbxproj - cd - - fi - - # macOS - if [ ! -d "$XCODE_MACOS_PROJ_DIR" ]; then - mkdir -p $XCODE_MACOS_PROJ_DIR - cd $XCODE_MACOS_PROJ_DIR - $CMAKE -G Xcode ../../ -DMACOS_FRAMEWORK=1 - cd - - fi - fi -} - -# Build framework for iOS (with embedded static library) -ios() -{ - if [[ ! $OSNAME = *"darwin"* ]]; then - exit 0 - fi - generate_projects # if needed - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - - cd $XCODE_IOS_PROJ_DIR - # Framework - xcodebuild -arch arm64 -target zt -configuration "$UPPERCASE_CONFIG" -sdk "iphoneos" - cd - - IOS_OUTPUT_DIR=$(pwd)/lib/$1/ios - mkdir -p $IOS_OUTPUT_DIR - rm -rf $IOS_OUTPUT_DIR/zt.framework # Remove prior to move to prevent error - mv $XCODE_IOS_PROJ_DIR/$UPPERCASE_CONFIG-iphoneos/* $IOS_OUTPUT_DIR - - cd $XCODE_IOS_SIMULATOR_PROJ_DIR - # Framework - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "iphonesimulator" - cd - - SIMULATOR_OUTPUT_DIR=$(pwd)/lib/$1/ios-simulator - mkdir -p $SIMULATOR_OUTPUT_DIR - rm -rf $SIMULATOR_OUTPUT_DIR/zt.framework # Remove prior to move to prevent error - mv $XCODE_IOS_SIMULATOR_PROJ_DIR/$UPPERCASE_CONFIG-iphonesimulator/* $SIMULATOR_OUTPUT_DIR - - # Combine the two archs - lipo -create $IOS_OUTPUT_DIR/zt.framework/zt $SIMULATOR_OUTPUT_DIR/zt.framework/zt -output $IOS_OUTPUT_DIR/zt.framework/zt - - # Clean up - rm -rf $SIMULATOR_OUTPUT_DIR -} - -# Build framework for current host (macOS only) -macos() -{ - if [[ ! $OSNAME = *"darwin"* ]]; then - exit 0 - fi - generate_projects # if needed - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - cd $XCODE_MACOS_PROJ_DIR - # Framework - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "macosx" - cd - - OUTPUT_DIR=$(pwd)/lib/$1/macos-universal - mkdir -p $OUTPUT_DIR - rm -rf $OUTPUT_DIR/zt.framework # Remove prior to move to prevent error - mv $XCODE_MACOS_PROJ_DIR/$UPPERCASE_CONFIG/* $OUTPUT_DIR -} - -# Build xcframework -xcframework() -{ - if [[ ! $OSNAME = *"darwin"* ]]; then - exit 0 - fi - generate_projects # if needed - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - OUTPUT_DIR=$(pwd)/lib/$1 - cd $XCODE_MACOS_PROJ_DIR - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "macosx" - - cd $XCODE_IOS_PROJ_DIR - xcodebuild -arch arm64 -target zt -configuration "$UPPERCASE_CONFIG" -sdk "iphoneos" - - cd $XCODE_IOS_SIMULATOR_PROJ_DIR - xcodebuild -target zt -configuration "$UPPERCASE_CONFIG" -sdk "iphonesimulator" - - mkdir -p $OUTPUT_DIR - - rm -rf $OUTPUT_DIR/zt.xcframework # Remove prior to move to prevent error - xcodebuild -create-xcframework \ - -framework $XCODE_MACOS_PROJ_DIR/$UPPERCASE_CONFIG/zt.framework \ - -framework $XCODE_IOS_PROJ_DIR/$UPPERCASE_CONFIG-iphoneos/zt.framework \ - -framework $XCODE_IOS_SIMULATOR_PROJ_DIR/$UPPERCASE_CONFIG-iphonesimulator/zt.framework \ - -output $OUTPUT_DIR/zt.xcframework -} - -# Build Java JAR for current host (uses JNI) -host_jar() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - copy_root_java_sources_to_projects - NORMALIZED_OSNAME=$OSNAME - if [[ $OSNAME = *"darwin"* ]]; then - DYNAMIC_LIB_NAME="libzt.dylib" - NORMALIZED_OSNAME="macos" - fi - if [[ $OSNAME = *"linux"* ]]; then - DYNAMIC_LIB_NAME="libzt.so" - fi - LIB_OUTPUT_DIR=$(pwd)/lib/$1/${NORMALIZED_OSNAME}-$(uname -m) - mkdir -p $LIB_OUTPUT_DIR - rm -rf $LIB_OUTPUT_DIR/zt.jar - # Build dynamic library - BUILD_DIR=$(pwd)/tmp/${NORMALIZED_OSNAME}-$(uname -m)-jni-$1 - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - $CMAKE -H. -B$BUILD_DIR -DCMAKE_BUILD_TYPE=$UPPERCASE_CONFIG -DSDK_JNI=ON "-DSDK_JNI=1" - $CMAKE --build $BUILD_DIR $BUILD_CONCURRENCY - # Copy dynamic library from previous build step - # And, remove any lib that may exist prior. We don't want accidental successes - cd $(pwd)/ports/java - rm $DYNAMIC_LIB_NAME - mv $BUILD_DIR/lib/$DYNAMIC_LIB_NAME . - # Begin constructing JAR - export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 - javac com/zerotier/libzt/*.java - jar cf zt.jar $DYNAMIC_LIB_NAME com/zerotier/libzt/*.class - rm $DYNAMIC_LIB_NAME - cd - - # Move completed JAR - LIB_OUTPUT_DIR=$(pwd)/lib/$1/${NORMALIZED_OSNAME}-$(uname -m) - mkdir -p $LIB_OUTPUT_DIR - mv $(pwd)/ports/java/zt.jar $LIB_OUTPUT_DIR - # Build sample app classes - # Remove old dynamic library if it exists - rm -rf $(pwd)/examples/java/$DYNAMIC_LIB_NAME - javac -cp ".:"$LIB_OUTPUT_DIR/zt.jar $(pwd)/examples/java/src/com/zerotier/libzt/javasimpleexample/*.java - # To run: - # jar xf $LIB_OUTPUT_DIR/zt.jar libzt.dylib - # cp libzt.dylib examples/java/ - # java -cp "lib/debug/macos-x86_64/zt.jar:examples/java/src/main/java" ExampleApp -} - -# Build all ordinary library types for current host -host_pinvoke() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - NORMALIZED_OSNAME=$OSNAME - if [[ $OSNAME = *"darwin"* ]]; then - DYNAMIC_LIB_NAME="libzt.dylib" - NORMALIZED_OSNAME="macos" - fi - if [[ $OSNAME = *"linux"* ]]; then - DYNAMIC_LIB_NAME="libzt.so" - fi - # CMake build files - BUILD_DIR=$(pwd)/tmp/${NORMALIZED_OSNAME}-$(uname -m)-$1 - mkdir -p $BUILD_DIR - # Where to place results - BIN_OUTPUT_DIR=$(pwd)/bin/$1/${NORMALIZED_OSNAME}-$(uname -m) - mkdir -p $BIN_OUTPUT_DIR - rm -rf $BIN_OUTPUT_DIR/* - LIB_OUTPUT_DIR=$(pwd)/lib/$1/${NORMALIZED_OSNAME}-$(uname -m)-pinvoke - mkdir -p $LIB_OUTPUT_DIR - rm -rf $LIB_OUTPUT_DIR/libzt.a $LIB_OUTPUT_DIR/$DYNAMIC_LIB_NAME $LIB_OUTPUT_DIR/libztcore.a - # Build - cmake -DZTS_PINVOKE=True -H. -B$BUILD_DIR -DCMAKE_BUILD_TYPE=$1 - $CMAKE --build $BUILD_DIR $BUILD_CONCURRENCY - # Move and clean up - cp -f $BUILD_DIR/bin/* $BIN_OUTPUT_DIR - cp -f $BUILD_DIR/lib/* $LIB_OUTPUT_DIR - clean_post_build -} - -# Build all ordinary library types for current host -host() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - NORMALIZED_OSNAME=$OSNAME - if [[ $OSNAME = *"darwin"* ]]; then - DYNAMIC_LIB_NAME="libzt.dylib" - NORMALIZED_OSNAME="macos" - fi - if [[ $OSNAME = *"linux"* ]]; then - DYNAMIC_LIB_NAME="libzt.so" - fi - # CMake build files - BUILD_DIR=$(pwd)/tmp/${NORMALIZED_OSNAME}-$(uname -m)-$1 - mkdir -p $BUILD_DIR - # Where to place results - BIN_OUTPUT_DIR=$(pwd)/bin/$1/${NORMALIZED_OSNAME}-$(uname -m) - mkdir -p $BIN_OUTPUT_DIR - rm -rf $BIN_OUTPUT_DIR/* - LIB_OUTPUT_DIR=$(pwd)/lib/$1/${NORMALIZED_OSNAME}-$(uname -m) - mkdir -p $LIB_OUTPUT_DIR - rm -rf $LIB_OUTPUT_DIR/libzt.a $LIB_OUTPUT_DIR/$DYNAMIC_LIB_NAME $LIB_OUTPUT_DIR/libztcore.a - # Build - $CMAKE -H. -B$BUILD_DIR -DCMAKE_BUILD_TYPE=$1 - $CMAKE --build $BUILD_DIR $BUILD_CONCURRENCY - # Move and clean up - cp -f $BUILD_DIR/bin/* $BIN_OUTPUT_DIR - cp -f $BUILD_DIR/lib/* $LIB_OUTPUT_DIR - clean_post_build -} - -# Set important variables for Android builds -set_android_env() -{ - # Set ANDROID_HOME because setting sdk.dir in local.properties isn't always reliable - #export PATH=/Library/Java/JavaVirtualMachines/$JDK/Contents/Home/bin/:${PATH} - #export PATH=/Users/$USER/Library/Android/sdk/platform-tools/:${PATH} - GRADLE_ARGS=--stacktrace - #ANDROID_APP_NAME=com.example.mynewestapplication - # for our purposes we limit this to execution on macOS - if [[ $OSNAME = *"linux"* ]]; then - export ANDROID_HOME=/usr/lib/android-sdk/ - fi - if [[ $OSNAME = *"darwin"* ]]; then - export ANDROID_HOME=/Users/$USER/Library/Android/sdk - fi -} - -# Build android AAR -android() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - # Unsure why, but Gradle's build script chokes on this non-source file now - rm -rf ext/ZeroTierOne/ext/miniupnpc/VERSION - export PATH=$ANDROID_HOME/cmdline-tools/tools/bin:$PATH - set_android_env - # Copy source files into project - cp -f src/bindings/java/*.java ${ANDROID_PROJ_DIR}/app/src/main/java/com/zerotier/libzt - # CMake build files - BUILD_DIR=$(pwd)/tmp/android-$1 - mkdir -p $BUILD_DIR - # If clean requested, remove temp build dir - if [[ $1 = *"clean"* ]]; then - rm -rf $BUILD_DIR - exit 0 - fi - # Where to place results - LIB_OUTPUT_DIR=$(pwd)/lib/$1/android - mkdir -p $LIB_OUTPUT_DIR - # Build - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - CMAKE_FLAGS="-DSDK_JNI=1 -DSDK_JNI=ON" - cd $ANDROID_PROJ_DIR - ./gradlew $GRADLE_ARGS assemble$UPPERCASE_CONFIG # assembleRelease / assembleDebug - mv $ANDROID_PROJ_DIR/app/build/outputs/aar/*.aar \ - $LIB_OUTPUT_DIR/libzt-$1.aar - cd - -} - -# Remove intermediate object files and/or libraries -clean_post_build() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - find $(pwd)/lib -type f -name 'liblwip_pic.a' -exec rm {} + - find $(pwd)/lib -type f -name 'liblwip.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libminiupnpc.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libminiupnpc_pic.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libnatpmp.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libnatpmp_pic.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libzto_pic.a' -exec rm {} + - find $(pwd)/lib -type f -name 'libzt_pic.a' -exec rm {} + -} - -# General clean -clean() -{ - # Remove all temporary build files, products, etc - rm -rf builds tmp lib bin products - rm -f *.o *.s *.exp *.lib *.core core - # Generally search for and remove object files, libraries, etc - find . -path './*_products' -prune -type f \( -name '*.dylib' -o -name '*.dll' -o -name '*.so' -o -name \ - '*.a' -o -name '*.o' -o -name '*.exe' -o -name '*.o.d' -o -name \ - '*.out' -o -name '*.log' -o -name '*.dSYM' -o -name '*.class' \) -delete - # Remove any sources copied to project directories - rm -rf ports/android/app/src/main/java/com/zerotier/libzt/*.java - rm -rf ports/java/com/zerotier/libzt/*.java -} - -# Copy and rename Android AAR from lib to example app directory -prep_android_example() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - mkdir -p examples/android/ExampleAndroidApp/app/libs/ - cp -f lib/$1/android/libzt-$1.aar \ - examples/android/ExampleAndroidApp/app/libs/libzt.aar -} -# Clean Android project -clean_android_project() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - set_android_env - ANDROID_EXAMPLE_PROJ_DIR="examples/android/ExampleAndroidApp" - cd $ANDROID_EXAMPLE_PROJ_DIR - ./gradlew $GRADLE_ARGS clean - ./gradlew $GRADLE_ARGS cleanBuildCache - cd - -} -# Build APK from AAR and sources -build_android_app() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - set_android_env - ANDROID_EXAMPLE_PROJ_DIR="examples/android/ExampleAndroidApp" - UPPERCASE_CONFIG="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}" - cd $ANDROID_EXAMPLE_PROJ_DIR - ./gradlew assemble$UPPERCASE_CONFIG - cd - -} -# Stops an Android app that is already installed on device -stop_android_app() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - set_android_env - adb shell am force-stop $ANDROID_APP_NAME -} -# Starts an Android app that is already installed on device -start_android_app() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - set_android_env - adb shell monkey -p $ANDROID_APP_NAME 1 -} -# Copy and install example Android app on device -install_android_app() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - set_android_env - if [[ $1 = "release" ]]; then - APKNAME=app-$1-"unsigned" - else - APKNAME=app-$1 - fi - APK=examples/android/ExampleAndroidApp/app/build/outputs/apk/$1/$APKNAME.apk - echo "Installing $APK ..." - adb install -r $APK -} -# Perform all steps necessary to run a new instance of the app on device -run_android_app() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - stop_android_app - prep_android_example $1 - clean_android_project - # The following two functions take 'debug' as an argument regardless - # of the build type since the native code is built with the proper - # configuration anyway. - build_android_app "debug" - install_android_app "debug" - start_android_app -} -# View ADB logs of running Android app -android_app_log() -{ - set_android_env - if [[ $OSNAME = *"darwin"* ]]; then - adb logcat - fi -} -# View ADB logs of running Android app (filtered, must restart for each app re-launch) -android_app_log_filtered() -{ - set_android_env - if [[ $OSNAME = *"darwin"* ]]; then - adb logcat | grep -F "`adb shell ps | grep $ANDROID_APP_NAME | cut -c10-15`" - fi -} - - -# Copy java sources to projects before build process. This is so -# that we only have to maintain one set of sources for multiple java- -# based projects. -copy_root_java_sources_to_projects() -{ - cp -f src/bindings/java/*.java ports/java/com/zerotier/libzt/ -} - -# At the end of build stage, print contents and trees for inspection -display() -{ - find $(pwd)/lib -type f -name 'zt.jar' -exec echo -e "\n" \; -exec ls {} \; -exec jar tf {} + - echo -e "\n" - tree $(pwd)/lib -} - -# Merge all remotely-built targets. This is used before dist() -merge() -{ - if [ -d "darwin-x86_64_products" ]; then - rsync -a darwin-x86_64_products/ products/ - else - echo "Warning: darwin-x86_64_products is missing" - fi - # x86_64 64-bit linux - REMOTE_PRODUCTS_DIR=linux-x86_64_products - if [ -d "$REMOTE_PRODUCTS_DIR" ]; then - rsync -a $REMOTE_PRODUCTS_DIR/ products/ - echo "Merged products from " $REMOTE_PRODUCTS_DIR " to " products - else - echo "Warning: $REMOTE_PRODUCTS_DIR is missing" - fi - # armv7l linux - REMOTE_PRODUCTS_DIR=linux-armv7l_products - if [ -d "$REMOTE_PRODUCTS_DIR" ]; then - rsync -a $REMOTE_PRODUCTS_DIR/ products/ - echo "Merged products from " $REMOTE_PRODUCTS_DIR " to " products - else - echo "Warning: $REMOTE_PRODUCTS_DIR is missing" - fi - # armv6l linux - REMOTE_PRODUCTS_DIR=linux-armv6l_products - if [ -d "$REMOTE_PRODUCTS_DIR" ]; then - rsync -a $REMOTE_PRODUCTS_DIR/ products/ - echo "Merged products from " $REMOTE_PRODUCTS_DIR " to " products - else - echo "Warning: $REMOTE_PRODUCTS_DIR is missing" - fi - # 32/64-bit windows - REMOTE_PRODUCTS_DIR=win_products - if [ -d "$REMOTE_PRODUCTS_DIR" ]; then - rsync -a $REMOTE_PRODUCTS_DIR/ products/ - echo "Merged products from " $REMOTE_PRODUCTS_DIR " to " products - else - echo "Warning: $REMOTE_PRODUCTS_DIR is missing" - fi -} - -# On hosts which are not the final packaging platform (e.g. armv7, armv6l, etc) -# we will rename the products directory so that we can merge() it at a later -# stage on the packaging platform -wrap() -{ - ARCH_WRAP_DIR=$OSNAME"-"$(uname -m)_products - cp -rf lib $ARCH_WRAP_DIR - echo "Copied products to:" $ARCH_WRAP_DIR - PROD_FILENAME=$ARCH_WRAP_DIR.tar.gz - tar --exclude=$PROD_FILENAME -zcvf $PROD_FILENAME -C $ARCH_WRAP_DIR . -} - -# Renames and copies licenses for libzt and each of its dependencies -package_licenses() -{ - CURR_DIR=$1 - DEST_DIR=$2 - mkdir -p $DEST_DIR - cp $CURR_DIR/ext/lwip/COPYING $DEST_DIR/LWIP-LICENSE.BSD - cp $CURR_DIR/ext/concurrentqueue/LICENSE.md $DEST_DIR/CONCURRENTQUEUE-LICENSE.BSD - cp $CURR_DIR/LICENSE.txt $DEST_DIR/ZEROTIER-LICENSE.BSL-1.1 - cp $CURR_DIR/include/net/ROUTE_H-LICENSE.APSL $DEST_DIR/ROUTE_H-LICENSE.APSL - cp $CURR_DIR/include/net/ROUTE_H-LICENSE $DEST_DIR/ROUTE_H-LICENSE -} - -# Copies binaries, documentation, licenses, source, etc into a products -# directory and then tarballs everything together -package_everything() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - LIBZT_VERSION=$(git describe) - PROD_NAME=$LIBZT_VERSION-$(date '+%Y%m%d_%H-%M')-$1 - PROD_DIR=$(pwd)/products/$PROD_NAME/ - # Make products directory - # Licenses - package_licenses $(pwd) $PROD_DIR/licenses - # Examples - mkdir -p $PROD_DIR/examples - cp examples/cpp/* $PROD_DIR/examples - # Source - mkdir -p $PROD_DIR/src - cp src/*.cpp src/*.hpp src/*.c src/*.h $PROD_DIR/src - cp $(pwd)/README.pdf $PROD_DIR/README.pdf - # Header(s) - mkdir -p $PROD_DIR/include - cp $(pwd)/include/*.h $PROD_DIR/include - # Libraries - mkdir -p $PROD_DIR/lib - cp -r $(pwd)/products/$1/* $PROD_DIR/lib - rm -rf $(pwd)/products/$1 - # Clean - find $PROD_DIR -type f \( -name '*.DS_Store' -o -name 'thumbs.db' \) -delete - # Record the version (and each submodule's version) - echo "$(git describe)" > $PROD_DIR/VERSION - echo -e "$(git submodule status | awk '{$1=$1};1')" >> $PROD_DIR/VERSION - echo -e "$(cat ext/ZeroTierOne/version.h | grep ZEROTIER_ONE_VERSION | sed 's/\#define//g' | awk '{$1=$1};1')" >> $PROD_DIR/VERSION - echo "$(date)" >> $PROD_DIR/VERSION - # Tar everything - PROD_FILENAME=$(pwd)/products/$PROD_NAME.tar.gz - tar --exclude=$PROD_FILENAME -zcvf $PROD_FILENAME -C $PROD_DIR . - if [[ $OSNAME = *"darwin"* ]]; then - md5 $PROD_FILENAME - fi - if [[ $OSNAME = *"linux"* ]]; then - md5sum $PROD_FILENAME - fi - # Print results for post-build inspection - echo -e "\n" - tree $PROD_DIR - cat $PROD_DIR/VERSION - # Final check. Display warnings if anything is missing - FILES="VERSION - README.md - README.pdf - reference/errno.h - licenses/LWIP-LICENSE.BSD - licenses/CONCURRENTQUEUE-LICENSE.BSD - licenses/ZEROTIER-LICENSE.BSL-1.1 - licenses/ROUTE_H-LICENSE.APSL - licenses/ROUTE_H-LICENSE - licenses/LWIP-LICENSE.BSD" - for f in $FILES - do - if [ ! -f "$PROD_DIR$f" ]; then - echo "Warning: $PROD_DIR$f is missing" - fi - done -} - -# Generates a source-only tarball -sdist() -{ - VERSION=$(git describe --abbrev=0) - TARBALL_DIR="libzt-${VERSION}" - TARBALL_NAME=libzt-${VERSION}-source.tar.gz - PROD_DIR=$(pwd)/products/ - mkdir -p $PROD_DIR - # - mkdir ${TARBALL_DIR} - # primary sources - cp -rf src ${TARBALL_DIR}/src - cp -rf include ${TARBALL_DIR}/include - # important build scripts - cp Makefile ${TARBALL_DIR} - cp CMakeLists.txt ${TARBALL_DIR} - cp *.md ${TARBALL_DIR} - cp *.sh ${TARBALL_DIR} - cp *.bat ${TARBALL_DIR} - # submodules/dependencies - # lwIP - mkdir ${TARBALL_DIR}/ext - mkdir -p ${TARBALL_DIR}/ext/lwip/src - cp -rf ext/lwip/src/api ${TARBALL_DIR}/ext/lwip/src - cp -rf ext/lwip/src/core ${TARBALL_DIR}/ext/lwip/src - cp -rf ext/lwip/src/include ${TARBALL_DIR}/ext/lwip/src - cp -rf ext/lwip/src/netif ${TARBALL_DIR}/ext/lwip/src - # lwIP ports - mkdir -p ${TARBALL_DIR}/ext/lwip-contrib/ports - cp -rf ext/lwip-contrib/ports/unix ${TARBALL_DIR}/ext/lwip-contrib/ports - cp -rf ext/lwip-contrib/ports/win32 ${TARBALL_DIR}/ext/lwip-contrib/ports - # ZeroTierOne - mkdir ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/*.h ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/controller ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/ext ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/include ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/node ${TARBALL_DIR}/ext/ZeroTierOne - cp -rf ext/ZeroTierOne/osdep ${TARBALL_DIR}/ext/ZeroTierOne - # - # Perform selective removal - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/bin - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/tap-mac - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/librethinkdbxx - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/installfiles - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/curl-* - rm -rf ${TARBALL_DIR}/ext/ZeroTierOne/ext/http-parser - # - mkdir ${TARBALL_DIR}/ext/concurrentqueue - cp -rf ext/concurrentqueue/*.h ${TARBALL_DIR}/ext/concurrentqueue - # Licenses - package_licenses $(pwd) $TARBALL_DIR/licenses - # Tarball everything and display the results - tar -cvf ${TARBALL_NAME} ${TARBALL_DIR} - tree ${TARBALL_DIR} - rm -rf ${TARBALL_DIR} - mv ${TARBALL_NAME} ${PROD_DIR} -} - -# Package both debug and release -bdist() -{ - echo "Executing task: " ${FUNCNAME[ 0 ]} "(" $1 ")" - package_everything "debug" - package_everything "release" -} - -# Generate a markdown CHANGELOG from git-log -update_changelog() -{ - first_commit=$(git rev-list --max-parents=0 HEAD) - git for-each-ref --sort=-refname --format="## [%(refname:short)] - %(taggerdate:short) &(newline)*** &(newline)- %(subject) %(body)" refs/tags > CHANGELOG.md - gsed -i '''s/\&(newline)/\n/' CHANGELOG.md # replace first instance - gsed -i '''s/\&(newline)/\n/' CHANGELOG.md # replace second instance - echo -e "\n" >> CHANGELOG.md - for curr_tag in $(git tag -l --sort=-v:refname) - do - prev_tag=$(git describe --abbrev=0 ${curr_tag}^) - if [ -z "${prev_tag}" ] - then - prev_tag=${first_commit} - fi - echo "[${curr_tag}]: https://github.com/zerotier/libzt/compare/${prev_tag}..${curr_tag}" >> CHANGELOG.md - done -} - -# List all functions in this script (just for convenience) -list() -{ - IFS=$'\n' - for f in $(declare -F); do - echo "${f:11}" - done -} - -"$@" diff --git a/examples/README.md b/examples/README.md index bcfb75f..759b5db 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,57 +1 @@ -Useful things to know - ===== - -### IDENTITIES and AUTHORIZATION: - -Upon the first execution of this code, a new identity will be generated and placed in the location given in the first argument to zts_start(path, ...). If you accidentally duplicate the identity files and use them simultaneously in a different node instance **you will experience undefined behavior** and it is likely that nothing will work. - -You must authorize the node ID provided by the `ZTS_EVENT_NODE_ONLINE` callback to join your network, otherwise nothing will happen. This can be done manually or via our web API: https://my.zerotier.com/help/api - -An exception to the above rule is if you are using an Ad-hoc network, it has no controller and therefore requires no authorization. - - -### ESTABLISHING A CONNECTION: - -Creating a standard socket connection generally works the same as it would using an ordinary socket interface, however with libzt there is a subtle difference in how connections are established which may cause confusion: - -The underlying virtual ZT layer creates what are called "transport-triggered links" between nodes. That is, links are not established until an attempt to communicate with a peer has taken place. The side effect is that the first few packets sent from a libzt instance are usually relayed via our free infrastructure and it isn't until a root server has passed contact information to both peers that a direct connection will be established. Therefore, it is required that multiple connection attempts be undertaken when initially communicating with a peer. After a transport-triggered link is established libzt will inform you via `ZTS_EVENT_PEER_DIRECT` for a specific peer ID. No action is required on your part for this callback event. - -*Note: In these initial moments before `ZTS_EVENT_PEER_DIRECT` has been received for a specific peer, traffic may be slow, jittery and there may be high packet loss. This will subside within a couple of seconds.* - - -### ERROR HANDLING: - -libzt's API is actually composed of two categories of functions with slightly different error reporting mechanisms. - -- Category 1: Control functions (`zts_start`, `zts_join`, `zts_get_peer_status`, etc). Errors returned by these functions can be any of the following: - -``` -ZTS_ERR_OK // No error -ZTS_ERR_SOCKET // Socket error, see zts_errno -ZTS_ERR_SERVICE // You probably did something at the wrong time -ZTS_ERR_ARG // Invalid argument -ZTS_ERR_NO_RESULT // No result (not necessarily an error) -ZTS_ERR_GENERAL // Consider filing a bug report -``` - -- Category 2: Sockets (`zts_socket`, `zts_bind`, `zts_connect`, `zts_listen`, etc). Errors returned by these functions can be the same as the above. With the added possibility of `zts_errno` being set. Much like standard errno this will provide a more specific reason for an error's occurrence. See `ZeroTierSockets.h` for values. - - -### API COMPATIBILITY WITH HOST OS: - -While the ZeroTier socket interface can coexist with your host OS's own interface in the same file with no type and naming conflicts, try not to mix and match host OS/libzt structures, functions, or constants. It may look similar and may even work some of the time but there enough differences that it will cause headaches: - -If you are calling a `zts_*` function, use the appropriate `ZTS_*` constants: - -``` -zts_socket(ZTS_AF_INET6, ZTS_SOCK_DGRAM, 0); (CORRECT) -zts_socket(AF_INET6, SOCK_DGRAM, 0); (INCORRECT) -``` - -If you are calling a `zts_*` function, use the appropriate `zts_*` structure: - -``` -struct zts_sockaddr_in in4; <------ Note the zts_* prefix - ... -zts_bind(fd, (struct zts_sockaddr *)&in4, sizeof(struct zts_sockaddr_in)) < 0) -``` \ No newline at end of file +Please read the [Common pitfalls](../include/README.md#common-pitfalls) section in the C API reference documentation. \ No newline at end of file