diff --git a/.drone.jsonnet b/.drone.jsonnet index 87aaf71ff1..29972c0641 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -279,6 +279,33 @@ local mac_builder(name, ], }; +// iphone builder +local iphone_builder(name, + build_type='Release', + werror=true, + cmake_extra='', + extra_cmds=[], + jobs=6, + allow_fail=false) = { + kind: 'pipeline', + type: 'exec', + name: name, + platform: { os: 'darwin', arch: 'amd64' }, + steps: [ + { name: 'submodules', commands: submodule_commands }, + { + name: 'build', + environment: { SSH_KEY: { from_secret: 'SSH_KEY' } }, + commands: [ + 'echo "Building on ${DRONE_STAGE_MACHINE}"', + 'export CMAKE_BUILD_PARALLEL_LEVEL=6', + 'ulimit -n 1024', // because macos sets ulimit to 256 for some reason yeah idk + './contrib/ios.sh ' + ci_mirror_opts, + ] + extra_cmds, + }, + ], +}; + local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { kind: 'pipeline', type: 'docker', @@ -402,6 +429,10 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { deb_builder(docker_base + 'ubuntu-jammy-builder', 'jammy', 'ubuntu/jammy'), deb_builder(docker_base + 'debian-sid-builder', 'sid', 'debian/sid', arch='arm64'), + // iphone builds: + iphone_builder('iOS (embedded lokinet)', build_type='Debug', extra_cmds=[ + 'UPLOAD_OS=iphone ./contrib/ci/drone-static-upload.sh', + ]), // Macos builds: mac_builder('macOS (Release)'), mac_builder('macOS (Debug)', build_type='Debug'), diff --git a/.gitmodules b/.gitmodules index 60d5d96217..56afbcada7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -36,3 +36,9 @@ [submodule "external/oxen-encoding"] path = external/oxen-encoding url = https://github.com/oxen-io/oxen-encoding.git +[submodule "external/libuv"] + path = external/libuv + url = https://github.com/libuv/libuv +[submodule "external/ios-cmake"] + path = external/ios-cmake + url = https://github.com/leetal/ios-cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 83f6d3e410..e2700ec23b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,9 @@ if(APPLE AND BUILD_DAEMON) set(LANGS ${LANGS} OBJC Swift) endif() + find_program(CCACHE_PROGRAM ccache) + if(CCACHE_PROGRAM) foreach(lang ${LANGS}) if(NOT DEFINED CMAKE_${lang}_COMPILER_LAUNCHER AND NOT CMAKE_${lang}_COMPILER MATCHES ".*/ccache") @@ -50,7 +52,8 @@ option(USE_AVX2 "enable avx2 code" OFF) option(USE_NETNS "enable networking namespace support. Linux only" OFF) option(NATIVE_BUILD "optimise for host system and FPU" ON) option(EMBEDDED_CFG "optimise for older hardware or embedded systems" OFF) -option(BUILD_LIBLOKINET "build liblokinet.so" ON) +option(BUILD_LIBLOKINET "build liblokinet.so" OFF) +option(BUILD_EMBEDDED_LOKINET "build embedded lokinet" OFF) option(XSAN "use sanitiser, if your system has it (requires -DCMAKE_BUILD_TYPE=Debug)" OFF) option(USE_JEMALLOC "Link to jemalloc for memory allocations, if found" ON) option(TESTNET "testnet build" OFF) @@ -71,8 +74,10 @@ option(STATIC_LINK "link statically against dependencies" ${BUILD_STATIC_DEPS}) if(BUILD_STATIC_DEPS AND NOT STATIC_LINK) message(FATAL_ERROR "Option BUILD_STATIC_DEPS requires STATIC_LINK to be enabled as well") endif() + if(BUILD_STATIC_DEPS) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) + include(cmake/combine_archives.cmake) include(StaticBuild) endif() @@ -138,6 +143,7 @@ find_package(PkgConfig REQUIRED) if(NOT BUILD_STATIC_DEPS) pkg_check_modules(LIBUV libuv>=1.18.0 IMPORTED_TARGET) endif() + if(LIBUV_FOUND AND NOT BUILD_STATIC_DEPS) add_library(libuv INTERFACE) target_link_libraries(libuv INTERFACE PkgConfig::LIBUV) @@ -197,23 +203,32 @@ if (WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE) include(cmake/cross_compile.cmake) endif() -if(NOT APPLE) - if(NATIVE_BUILD) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le) - add_compile_options(-mcpu=native -mtune=native) - else() - add_compile_options(-march=native -mtune=native) - endif() - elseif(NOT NON_PC_TARGET) - if (USE_AVX2) - add_compile_options(-march=haswell -mtune=haswell -mfpmath=sse) - else() - # Public binary releases - add_compile_options(-march=nocona -mtune=haswell -mfpmath=sse) - endif() +if(APPLE) + if(IOS AND ARCH STREQUAL "arm64") + message(STATUS "IOS: Changing arch from arm64 to armv8") + add_compile_options(-march=armv8) + elseif(IOS AND ARCH STREQUAL "x86_64") + message(STATUS "IOS: Changing arch from x86_64 to x86-64") + add_compile_options(-march=x86-64) + endif() +endif() + +if(NATIVE_BUILD) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le) + add_compile_options(-mcpu=native -mtune=native) + else() + add_compile_options(-march=native -mtune=native) + endif() +elseif(NOT NON_PC_TARGET) + if (USE_AVX2) + add_compile_options(-march=haswell -mtune=haswell -mfpmath=sse) + else() + # Public binary releases + add_compile_options(-march=nocona -mtune=haswell -mfpmath=sse) endif() endif() + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake index 3ddbe97579..cf736f275b 100644 --- a/cmake/StaticBuild.cmake +++ b/cmake/StaticBuild.cmake @@ -48,20 +48,13 @@ set(ZMQ_SOURCE zeromq-${ZMQ_VERSION}.tar.gz) set(ZMQ_HASH SHA512=e198ef9f82d392754caadd547537666d4fba0afd7d027749b3adae450516bcf284d241d4616cad3cb4ad9af8c10373d456de92dc6d115b037941659f141e7c0e CACHE STRING "libzmq source hash") -set(LIBUV_VERSION 1.44.1 CACHE STRING "libuv version") -set(LIBUV_MIRROR ${LOCAL_MIRROR} https://dist.libuv.org/dist/v${LIBUV_VERSION} - CACHE STRING "libuv mirror(s)") -set(LIBUV_SOURCE libuv-v${LIBUV_VERSION}.tar.gz) -set(LIBUV_HASH SHA512=b4f8944e2c79e3a6a31ded6cccbe4c0eeada50db6bc8a448d7015642795012a4b80ffeef7ca455bb093c59a8950d0e1430566c3c2fa87b73f82699098162d834 - CACHE STRING "libuv source hash") - set(ZLIB_VERSION 1.2.12 CACHE STRING "zlib version") set(ZLIB_MIRROR ${LOCAL_MIRROR} https://zlib.net CACHE STRING "zlib mirror(s)") set(ZLIB_SOURCE zlib-${ZLIB_VERSION}.tar.gz) set(ZLIB_HASH SHA256=91844808532e5ce316b3c010929493c0244f3d37593afd6de04f71821d5136d9 CACHE STRING "zlib source hash") - + set(CURL_VERSION 7.83.1 CACHE STRING "curl version") set(CURL_MIRROR ${LOCAL_MIRROR} https://curl.haxx.se/download https://curl.askapache.com CACHE STRING "curl mirror(s)") @@ -105,15 +98,25 @@ function(add_static_target target ext_target libname) endfunction() - set(cross_host "") set(cross_rc "") + if(CMAKE_CROSSCOMPILING) - set(cross_host "--host=${ARCH_TRIPLET}") - if (ARCH_TRIPLET MATCHES mingw AND CMAKE_RC_COMPILER) - set(cross_rc "WINDRES=${CMAKE_RC_COMPILER}") + if(APPLE_TARGET_TRIPLE) + if(PLATFORM MATCHES "OS64" OR PLATFORM MATCHES "SIMULATORARM64") + set(APPLE_TARGET_TRIPLE aarch64-apple-ios) + elseif(PLATFORM MATCHES "SIMULATOR64") + set(APPLE_TARGET_TRIPLE x86_64-apple-ios) + endif() + set(cross_host "--host=${APPLE_TARGET_TRIPLE}") + else() + set(cross_host "--host=${ARCH_TRIPLET}") + if (ARCH_TRIPLET MATCHES mingw AND CMAKE_RC_COMPILER) + set(cross_rc "WINDRES=${CMAKE_RC_COMPILER}") + endif() endif() endif() + if(ANDROID) set(android_toolchain_suffix linux-android) set(android_compiler_suffix linux-android23) @@ -162,12 +165,6 @@ if(WITH_LTO) set(deps_CFLAGS "${deps_CFLAGS} -flto") endif() -if(APPLE) - set(deps_CFLAGS "${deps_CFLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - set(deps_CXXFLAGS "${deps_CXXFLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") -endif() - - if("${CMAKE_GENERATOR}" STREQUAL "Unix Makefiles") set(_make $(MAKE)) else() @@ -175,6 +172,18 @@ else() endif() +if(APPLE) + foreach(lang C CXX) + string(APPEND deps_${lang}FLAGS " ${CMAKE_${lang}_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT} ${CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(deps_noarch_${lang}FLAGS "${deps_${lang}FLAGS}") + foreach(arch ${CMAKE_OSX_ARCHITECTURES}) + string(APPEND deps_${lang}FLAGS " -arch ${arch}") + endforeach() + endforeach() +endif() + + + # Builds a target; takes the target name (e.g. "readline") and builds it in an external project with # target name suffixed with `_external`. Its upper-case value is used to get the download details # (from the variables set above). The following options are supported and passed through to @@ -214,16 +223,6 @@ function(build_external target) ) endfunction() -build_external(libuv - CONFIGURE_COMMAND ./autogen.sh && ./configure ${cross_host} ${cross_rc} --prefix=${DEPS_DESTDIR} --with-pic --disable-shared --enable-static "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" - BUILD_BYPRODUCTS - ${DEPS_DESTDIR}/lib/libuv.a - ${DEPS_DESTDIR}/include/uv.h - ) -add_static_target(libuv libuv_external libuv.a) -target_link_libraries(libuv INTERFACE ${CMAKE_DL_LIBS}) - - build_external(zlib CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS} -fPIC" ${cross_extra} ./configure --prefix=${DEPS_DESTDIR} --static BUILD_BYPRODUCTS @@ -243,6 +242,15 @@ if(CMAKE_CROSSCOMPILING) elseif(ANDROID) set(openssl_system_env SYSTEM=Linux MACHINE=${android_machine} LD=${deps_ld} RANLIB=${deps_ranlib} AR=${deps_ar}) set(openssl_extra_opts no-asm) + elseif(IOS) + get_filename_component(apple_toolchain "${CMAKE_C_COMPILER}" DIRECTORY) + get_filename_component(apple_sdk "${CMAKE_OSX_SYSROOT}" NAME) + if(NOT ${apple_toolchain} MATCHES Xcode OR NOT ${apple_sdk} MATCHES "iPhone(OS|Simulator)") + message(FATAL_ERROR "didn't find your toolchain and sdk correctly from ${CMAKE_C_COMPILER}/${CMAKE_OSX_SYSROOT}: found toolchain=${apple_toolchain}, sdk=${apple_sdk}") + endif() + set(openssl_system_env CROSS_COMPILE=${apple_toolchain}/ CROSS_TOP=${CMAKE_DEVELOPER_ROOT}/ CROSS_SDK=${apple_sdk}/) + set(openssl_configure_command ./Configure iphoneos-cross) + set(openssl_cc "clang") elseif(ARCH_TRIPLET STREQUAL mips64-linux-gnuabi64) set(openssl_system_env SYSTEM=Linux MACHINE=mips64) set(openssl_configure_command ./Configure linux64-mips64) @@ -265,12 +273,11 @@ elseif(CMAKE_C_FLAGS MATCHES "-march=armv7") set(openssl_system_env SYSTEM=Linux MACHINE=armv7) endif() - build_external(openssl - CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${deps_cc} ${openssl_system_env} ${openssl_configure_command} - --prefix=${DEPS_DESTDIR} ${openssl_extra_opts} no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost - no-heartbeats no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl2 no-ssl3 - no-static-engine no-tests no-weak-ssl-ciphers no-zlib no-zlib-dynamic "CFLAGS=${deps_CFLAGS}" + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CC=${openssl_cc} ${openssl_system_env} ${openssl_configure_command} + --prefix=${DEPS_DESTDIR} ${openssl_extra_opts} no-shared no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost + no-heartbeats no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-ssl-trace no-ssl2 no-ssl3 + no-static-engine no-tests no-weak-ssl-ciphers no-zlib-dynamic "CFLAGS=${deps_CFLAGS}" INSTALL_COMMAND ${_make} install_sw BUILD_BYPRODUCTS ${DEPS_DESTDIR}/lib/libssl.a ${DEPS_DESTDIR}/lib/libcrypto.a @@ -281,7 +288,6 @@ add_static_target(OpenSSL::Crypto openssl_external libcrypto.a) if(WIN32) target_link_libraries(OpenSSL::Crypto INTERFACE "ws2_32;crypt32;iphlpapi") endif() - set(OPENSSL_INCLUDE_DIR ${DEPS_DESTDIR}/include) set(OPENSSL_CRYPTO_LIBRARY ${DEPS_DESTDIR}/lib/libcrypto.a ${DEPS_DESTDIR}/lib/libssl.a) set(OPENSSL_VERSION 1.1.1) @@ -294,13 +300,19 @@ build_external(expat ) add_static_target(expat expat_external libexpat.a) + +set(unbound_extra) +if(APPLE AND IOS) + set(unbound_extra CPP=cpp) +endif() + build_external(unbound DEPENDS openssl_external expat_external CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} --prefix=${DEPS_DESTDIR} --disable-shared - --enable-static --with-libunbound-only --with-pic + --enable-static --with-libunbound-only --with-pic --disable-gost --$,enable,disable>-flto --with-ssl=${DEPS_DESTDIR} --with-libexpat=${DEPS_DESTDIR} - "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" + "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" ${unbound_extra} ) add_static_target(libunbound unbound_external libunbound.a) if(NOT WIN32) @@ -315,7 +327,10 @@ build_external(sodium CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} -- --enable-static --with-pic "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}") add_static_target(sodium sodium_external libsodium.a) -build_external(sqlite3) +build_external(sqlite3 CONFIGURE_COMMAND ./configure ${cross_host} ${cross_rc} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared --disable-readline --with-pic "CC=${deps_cc}" "CFLAGS=${deps_CFLAGS}" + BUILD_COMMAND true + INSTALL_COMMAND make install-includeHEADERS install-libLTLIBRARIES) + add_static_target(sqlite3 sqlite3_external libsqlite3.a) @@ -331,10 +346,16 @@ if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw) PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-wepoll.patch ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-closesocket.patch) endif() +set(zmq_cross_host "${cross_host}") +if(IOS AND cross_host MATCHES "-ios$") + # zmq doesn't like "-ios" for the host, so replace it with -darwin + string(REGEX REPLACE "-ios$" "-darwin" zmq_cross_host ${cross_host}) +endif() + build_external(zmq DEPENDS sodium_external ${zmq_patch} - CONFIGURE_COMMAND ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared + CONFIGURE_COMMAND ./configure ${zmq_cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared --disable-curve-keygen --enable-curve --disable-drafts --disable-libunwind --with-libsodium --without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror --disable-libbsd ${zmq_extra} "CC=${deps_cc}" "CXX=${deps_cxx}" "CFLAGS=${deps_CFLAGS} -fstack-protector" "CXXFLAGS=${deps_CXXFLAGS} -fstack-protector" diff --git a/cmake/combine_archives.cmake b/cmake/combine_archives.cmake new file mode 100644 index 0000000000..4e5a8051ca --- /dev/null +++ b/cmake/combine_archives.cmake @@ -0,0 +1,30 @@ +function(combine_archives output_archive) + set(FULL_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib${output_archive}.a) + set(output_archive_dummy_file ${CMAKE_CURRENT_BINARY_DIR}/${output_archive}.dummy.cpp) + add_custom_command(OUTPUT ${output_archive_dummy_file} + COMMAND touch ${output_archive_dummy_file} + DEPENDS ${ARGN}) + add_library(${output_archive} STATIC EXCLUDE_FROM_ALL ${output_archive_dummy_file}) + + if(NOT APPLE) + set(mri_file ${CMAKE_CURRENT_BINARY_DIR}/${output_archive}.mri) + set(mri_content "create ${FULL_OUTPUT_PATH}\n") + foreach(in_archive ${ARGN}) + string(APPEND mri_content "addlib $\n") + endforeach() + string(APPEND mri_content "save\nend\n") + file(GENERATE OUTPUT ${mri_file} CONTENT "${mri_content}") + + add_custom_command(TARGET ${output_archive} + POST_BUILD + COMMAND ar -M < ${mri_file}) + else() + set(merge_libs) + foreach(in_archive ${ARGN}) + list(APPEND merge_libs $) + endforeach() + add_custom_command(TARGET ${output_archive} + POST_BUILD + COMMAND /usr/bin/libtool -static -o ${FULL_OUTPUT_PATH} ${merge_libs}) + endif() +endfunction(combine_archives) diff --git a/contrib/android-configure.sh b/contrib/android-configure.sh index 2130b07cf2..80ba046051 100755 --- a/contrib/android-configure.sh +++ b/contrib/android-configure.sh @@ -37,7 +37,9 @@ for abi in $build_abis; do -DWITH_SYSTEMD=OFF \ -DFORCE_OXENMQ_SUBMODULE=ON \ -DFORCE_OXENC_SUBMODULE=ON \ - -DSUBMODULE_CHECK=OFF \ + -DFORCE_NLOHMANN_SUBMODULE=ON \ + -DFORCE_LIBUV_SUBMODULE=ON \ + -DSUBMODULE_CHECK=ON \ -DWITH_LTO=OFF \ -DCMAKE_BUILD_TYPE=Release \ $@ $root diff --git a/contrib/ci/drone-static-upload.sh b/contrib/ci/drone-static-upload.sh index 9449ff6dd9..432dc97b00 100755 --- a/contrib/ci/drone-static-upload.sh +++ b/contrib/ci/drone-static-upload.sh @@ -47,6 +47,9 @@ elif [ -e build-docs ]; then archive="$base.tar.xz" cp -av build-docs/docs/mkdocs.yml build-docs/docs/markdown "$base" tar cJvf "$archive" "$base" +elif [ -e build/iphone/ ]; then + archive="$base.tar.xz" + mv build/iphone/*.tar.xz "$archive" else cp -av daemon/lokinet daemon/lokinet-vpn "$base" cp -av ../contrib/bootstrap/mainnet.signed "$base/bootstrap.signed" diff --git a/contrib/cross.sh b/contrib/cross.sh index 0b7d66328e..2e29ba66a4 100755 --- a/contrib/cross.sh +++ b/contrib/cross.sh @@ -25,7 +25,10 @@ cmake_opts="-DBUILD_STATIC_DEPS=ON \ -DSTATIC_LINK=ON \ -DWITH_SYSTEMD=OFF \ -DFORCE_OXENMQ_SUBMODULE=ON \ - -DSUBMODULE_CHECK=OFF \ + -DFORCE_OXENC_SUBMODULE=ON \ + -DFORCE_NLOHMANN_SUBMODULE=ON \ + -DFORCE_LIBUV_SUBMODULE=ON \ + -DSUBMODULE_CHECK=ON \ -DWITH_LTO=OFF \ -DWITH_BOOTSTRAP=OFF \ -DCMAKE_BUILD_TYPE=RelWithDeb" diff --git a/contrib/ios.sh b/contrib/ios.sh new file mode 100755 index 0000000000..d3e24e8009 --- /dev/null +++ b/contrib/ios.sh @@ -0,0 +1,85 @@ +#!/bin/bash +# +# Build the shit for iphone, only builds embeded lokinet + +set -e +set -x +if ! [ -f LICENSE ] || ! [ -d llarp ]; then + echo "You need to run this as ./contrib/ios.sh from the top-level lokinet project directory" +fi + + +root="$(readlink -f $(dirname $0)/../)" + +build_dir="$root/build/iphone" + +deviceArchs=(arm64) +devicePlat=(OS64) +simArchs=(arm64 x86_64) +simPlat=(SIMULATORARM64 SIMULATOR64) + +for i in "${!deviceArchs[@]}"; do + ./contrib/ios/ios-configure.sh "$build_dir/device/${deviceArchs[i]}" ${devicePlat[i]} $@ +done + +for i in "${!simArchs[@]}"; do + ./contrib/ios/ios-configure.sh "$build_dir/sim/${simArchs[i]}" ${simPlat[i]} $@ +done + +for targ in ${deviceArchs[@]} ; do + ./contrib/ios/ios-build.sh "$build_dir/device/$targ" +done + +for targ in ${simArchs[@]} ; do + ./contrib/ios/ios-build.sh "$build_dir/sim/$targ" +done + +pkg_name="iphone_lokinet_embedded_$(date +%s)" +pkg_dir="$build_dir/$pkg_name" + +# Combine and device/simulator libraries into a single file so XCode doesn't complain +function combineArchsIfNeeded() { + local group=$1 + local destination=$2 + shift; shift + local archs=("$@") + + if [ ${#archs[@]} -gt 1 ]; then + local dirs=("${archs[@]/#/$build_dir/${group}/}") + local libs=("${dirs[@]/%//llarp/liblokinet-embedded.a}") + + mkdir -p "$build_dir/$group/$destination/llarp" + lipo -create "${libs[@]}" -output "$build_dir/$group/${destination}/llarp/liblokinet-embedded.a" + fi +} + +deviceArchsString="${deviceArchs[*]}" +joinedDeviceArchs="${deviceArchsString// /_}" +simArchsString="${simArchs[*]}" +joinedSimArchs="${simArchsString// /_}" + +combineArchsIfNeeded "device" $joinedDeviceArchs ${deviceArchs[*]} +combineArchsIfNeeded "sim" $joinedSimArchs ${simArchs[*]} + +# Create a '.xcframework' so XCode can deal with the different architectures +xcodebuild -create-xcframework \ + -library "$build_dir/device/$joinedDeviceArchs/llarp/liblokinet-embedded.a" \ + -library "$build_dir/sim/$joinedSimArchs/llarp/liblokinet-embedded.a" \ + -output "$pkg_dir/libLokinet.xcframework" + +# Copy the headers over +mkdir -p "$pkg_dir/libLokinet.xcframework/lokinet" +cp -a "$root"/include/lokinet{,/*}.h "$pkg_dir/libLokinet.xcframework/lokinet" +mv "$pkg_dir/libLokinet.xcframework/lokinet/lokinet.h" "$pkg_dir/libLokinet.xcframework/lokinet.h" + +# The 'module.modulemap' is needed for XCode to be able to find the headers +echo -e 'module Lokinet {' > "$pkg_dir/libLokinet.xcframework/module.modulemap" +echo -e ' umbrella header "lokinet.h"' >> "$pkg_dir/libLokinet.xcframework/module.modulemap" +echo -e ' export *' >> "$pkg_dir/libLokinet.xcframework/module.modulemap" +echo -e '}' >> "$pkg_dir/libLokinet.xcframework/module.modulemap" + +# Archive the result +cd "$build_dir" +tar cfv "$pkg_name.tar" $pkg_name +cd - +xz -T 0 "$build_dir/$pkg_name.tar" diff --git a/contrib/ios/ios-build.sh b/contrib/ios/ios-build.sh new file mode 100755 index 0000000000..feeb5c3e36 --- /dev/null +++ b/contrib/ios/ios-build.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# +# Build the shit for iphone + +test -e $1 || ( echo "run ios-configure.sh first" ; exit 1 ) + +cmake --build $1 --target lokinet-embedded diff --git a/contrib/ios/ios-configure.sh b/contrib/ios/ios-configure.sh new file mode 100755 index 0000000000..342431aa53 --- /dev/null +++ b/contrib/ios/ios-configure.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# +# configure step for ios + +set -x + +root=$(readlink -f "$( dirname $0 )/../../") + +unset SDKROOT +export SDKROOT="$(xcrun --sdk iphoneos --show-sdk-path)" + +targ=$1 +plat=$2 +shift +shift + +mkdir -p $targ + +cmake \ + -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="$root/external/ios-cmake/ios.toolchain.cmake" -DPLATFORM=$plat -DDEPLOYMENT_TARGET=13 -DENABLE_VISIBILITY=ON -DENABLE_BITCODE=OFF \ + -DBUILD_STATIC_DEPS=ON \ + -DBUILD_PACKAGE=OFF \ + -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_TESTING=OFF \ + -DBUILD_EMBEDDED_LOKINET=ON \ + -DWITH_TESTS=OFF \ + -DNATIVE_BUILD=OFF \ + -DSTATIC_LINK=ON \ + -DWITH_SYSTEMD=OFF \ + -DWITH_BOOTSTRAP=OFF \ + -DBUILD_DAEMON=OFF \ + -DFORCE_OXENMQ_SUBMODULE=ON \ + -DFORCE_OXENC_SUBMODULE=ON \ + -DFORCE_NLOHMANN_SUBMODULE=ON \ + -DFORCE_LIBUV_SUBMODULE=ON \ + -DSUBMODULE_CHECK=ON \ + -DWITH_LTO=OFF \ + -DCMAKE_CXX_FLAGS='-Oz' -DCMAKE_C_FLAGS='-Oz' \ + -DCMAKE_BUILD_TYPE=Release \ + -S "$root" -B $targ \ + $@ diff --git a/contrib/ios/readme.txt b/contrib/ios/readme.txt new file mode 100644 index 0000000000..98e32894dd --- /dev/null +++ b/contrib/ios/readme.txt @@ -0,0 +1,10 @@ +our scientists have yet to reverse engineer the correct way to use the apple build process as dictated on the official apple documentation so we have a made a hack to make it work until that occurs. +the build process for embedded lokinet on iphone is as follows: + +* obtain holy water, sprinkle onto keyboard and single button trackpad accordingly. +* run ./contrib/ios.sh +* after it runs and the proper number of goats have been offered to the slaughter you will get an xz's tarball in the build/iphone/ directory + +additional cmake flags can be passed to ./contrib/ios.sh as command line arguments like so: + + $ ./contrib/ios.sh -DYOLO_SWAG=ON diff --git a/contrib/windows.sh b/contrib/windows.sh index 7520936e9e..e4fa53b18f 100755 --- a/contrib/windows.sh +++ b/contrib/windows.sh @@ -24,7 +24,9 @@ cmake \ -DWITH_SYSTEMD=OFF \ -DFORCE_OXENMQ_SUBMODULE=ON \ -DFORCE_OXENC_SUBMODULE=ON \ - -DSUBMODULE_CHECK=OFF \ + -DFORCE_NLOHMANN_SUBMODULE=ON \ + -DFORCE_LIBUV_SUBMODULE=ON \ + -DSUBMODULE_CHECK=ON \ -DWITH_LTO=OFF \ -DCMAKE_BUILD_TYPE=Release \ $@ .. diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 083d6bfb6c..f6718f3f7d 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -47,7 +47,7 @@ set(NTRU_AVX_SRC include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-mavx2 COMPILER_SUPPORTS_AVX2) check_cxx_compiler_flag(-mfma COMPILER_SUPPORTS_FMA) -if(COMPILER_SUPPORTS_AVX2 AND COMPILER_SUPPORTS_FMA AND (NOT ANDROID)) +if(COMPILER_SUPPORTS_AVX2 AND COMPILER_SUPPORTS_FMA AND (NOT (ANDROID OR IOS))) target_sources(lokinet-cryptography PRIVATE ${NTRU_AVX_SRC}) set_property(SOURCE ${NTRU_AVX_SRC} APPEND PROPERTY COMPILE_FLAGS "-mavx2 -mfma") message(STATUS "Building libntrup with runtime AVX2/FMA support") diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index b851ff9868..0377d8786f 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -23,6 +23,7 @@ if(SUBMODULE_CHECK) check_submodule(sqlite_orm) check_submodule(oxen-mq) check_submodule(oxen-encoding) + check_submodule(libuv) check_submodule(uvw) check_submodule(cpr) check_submodule(ngtcp2) @@ -55,6 +56,7 @@ system_or_submodule(OXENC oxenc liboxenc>=1.0.3 oxen-encoding) system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.12 oxen-mq) set(JSON_BuildTests OFF CACHE INTERNAL "") system_or_submodule(NLOHMANN nlohmann_json nlohmann_json>=3.7.0 nlohmann) +system_or_submodule(LIBUV uv_a libuv libuv) # TODO: select better version if(WITH_HIVE) @@ -75,7 +77,7 @@ target_link_libraries(sqlite_orm INTERFACE sqlite3) add_library(uvw INTERFACE) target_include_directories(uvw INTERFACE uvw/src) -target_link_libraries(uvw INTERFACE libuv) +target_link_libraries(uvw INTERFACE uv_a::uv_a) # ngtcp2 needs some massaging to build nicely: include(ngtcp2_lib) diff --git a/external/ios-cmake b/external/ios-cmake new file mode 160000 index 0000000000..ab8607a7f5 --- /dev/null +++ b/external/ios-cmake @@ -0,0 +1 @@ +Subproject commit ab8607a7f57970d99d590d420ecd8e2d7f9a9c77 diff --git a/external/libuv b/external/libuv new file mode 160000 index 0000000000..8bcd689c04 --- /dev/null +++ b/external/libuv @@ -0,0 +1 @@ +Subproject commit 8bcd689c048af5aab26842ac5ff903fa3192d57c diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 8be49a2369..389550615d 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -130,7 +130,7 @@ add_library(liblokinet dht/taglookup.cpp endpoint_base.cpp - + exit/context.cpp exit/endpoint.cpp exit/exit_messages.cpp @@ -223,7 +223,7 @@ add_library(liblokinet set_target_properties(liblokinet PROPERTIES OUTPUT_NAME lokinet) enable_lto(lokinet-util lokinet-platform liblokinet) - + if(TRACY_ROOT) target_sources(liblokinet PRIVATE ${TRACY_ROOT}/TracyClient.cpp) endif() @@ -265,6 +265,32 @@ if(BUILD_LIBLOKINET) add_log_tag(lokinet-shared) endif() +if(BUILD_EMBEDDED_LOKINET) + add_library(lokinet-embedded-api STATIC lokinet_shared.cpp) + target_link_libraries(lokinet-embedded-api PUBLIC liblokinet) + add_log_tag(lokinet-embedded-api) + combine_archives(lokinet-embedded + lokinet-embedded-api + lokinet-platform lokinet-util lokinet-cryptography sqlite3 ngtcp2_static + liblokinet + uv_a::uv_a + sodium + zlib + OpenSSL::SSL OpenSSL::Crypto + expat + libunbound + libzmq + oxenmq) + if(IOS) + set(lib_folder lib-${ARCH}) + else() + set(lib_folder lib) + endif() + install(TARGETS lokinet-embedded + ARCHIVE DESTINATION ${lib_folder} + EXCLUDE_FROM_ALL) +endif() + if(APPLE) add_subdirectory(apple) endif() diff --git a/llarp/vpn/null.hpp b/llarp/vpn/null.hpp new file mode 100644 index 0000000000..c247b99e9f --- /dev/null +++ b/llarp/vpn/null.hpp @@ -0,0 +1,96 @@ +#pragma once +#include +#include + +namespace llarp::vpn +{ + class NullInterface : public NetworkInterface + { + /// we use a pipe because it isnt going to poll itself + int m_pipe[2]; + + public: + NullInterface() + { + ::pipe(m_pipe); + } + + virtual ~NullInterface() + { + ::close(m_pipe[1]); + ::close(m_pipe[0]); + } + + int + PollFD() const override + { + return m_pipe[0]; + } + + /// the interface's name + std::string + IfName() const override + { + return ""; + } + + net::IPPacket + ReadNextPacket() override + { + return net::IPPacket{}; + } + + /// write a packet to the interface + /// returns false if we dropped it + bool WritePacket(net::IPPacket) override + { + return true; + } + }; + + class NopRouteManager : public IRouteManager + { + public: + void AddRoute(IPVariant_t, IPVariant_t) override{}; + + void DelRoute(IPVariant_t, IPVariant_t) override{}; + + void AddDefaultRouteViaInterface(std::string) override{}; + + void DelDefaultRouteViaInterface(std::string) override{}; + + void + AddRouteViaInterface(NetworkInterface&, IPRange) override{}; + + void + DelRouteViaInterface(NetworkInterface&, IPRange) override{}; + + std::vector GetGatewaysNotOnInterface(std::string) override + { + return {}; + } + }; + + class NullPlatform : public Platform + { + NopRouteManager _routes; + + public: + NullPlatform() : Platform{}, _routes{} + {} + + virtual ~NullPlatform() = default; + + std::shared_ptr + ObtainInterface(InterfaceInfo, AbstractRouter*) + { + return std::static_pointer_cast(std::make_shared()); + } + + IRouteManager& + RouteManager() override + { + return _routes; + } + }; +} // namespace llarp::vpn diff --git a/llarp/vpn/platform.cpp b/llarp/vpn/platform.cpp index 341e28fcba..b09586034b 100644 --- a/llarp/vpn/platform.cpp +++ b/llarp/vpn/platform.cpp @@ -1,6 +1,5 @@ -#include - +#include #ifdef _WIN32 #include "win32.hpp" #endif @@ -12,27 +11,20 @@ #endif #endif -#include - namespace llarp::vpn { std::shared_ptr MakeNativePlatform(llarp::Context* ctx) { (void)ctx; - std::shared_ptr plat; -#ifdef _WIN32 - plat = std::make_shared(); -#endif -#ifdef __linux__ -#ifdef ANDROID - plat = std::make_shared(ctx); -#else - plat = std::make_shared(); -#endif -#endif -#ifdef __APPLE__ - throw std::runtime_error{"not supported"}; + auto nullplat = std::make_shared(); + std::shared_ptr plat = nullplat; +#if defined(_WIN32) + plat = std::make_shared(); +#elif defined(ANDROID) + plat = std::make_shared(ctx); +#elif defined(__linux__) + plat = std::make_shared(); #endif return plat; }