diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..446610f --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,494 @@ +name: Build All Platforms and Release + +on: + push: + branches: + - 'master' + - 'main' + - 'trunk' + tags: + - '*' + pull_request: + branches: + - '*' + workflow_dispatch: + +jobs: + build-linux: + name: Build Linux (Ubuntu) with UPnP ON + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: install packages + run: | + sudo apt-get update + sudo apt-get install build-essential cmake libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev + + - name: build application + run: | + mkdir build + cd build + cmake -DWITH_UPNP=ON .. + make -j3 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-ubuntu + path: | + build/i2pd + build/vain + build/keygen + build/keyinfo + build/famtool + build/routerinfo + build/regaddr + build/regaddr_3ld + build/i2pbase64 + build/offlinekeys + build/b33address + build/regaddralias + build/x25519 + build/verifyhost + build/autoconf_i2pd + + build-macos: + name: Build macOS with UPnP ON + runs-on: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: Install dependencies + run: | + brew update + brew install boost miniupnpc openssl@1.1 zlib + + - name: Configure and build with CMake + run: | + mkdir build + cd build + cmake \ + -DWITH_UPNP=ON \ + -DOPENSSL_ROOT_DIR="$HOMEBREW_PREFIX/opt/openssl@1.1" \ + -DBOOST_ROOT="$HOMEBREW_PREFIX/opt/boost" \ + -DCMAKE_PREFIX_PATH="$HOMEBREW_PREFIX/opt/boost;$HOMEBREW_PREFIX/opt/miniupnpc;$HOMEBREW_PREFIX/opt/openssl@1.1" \ + -DZLIB_ROOT=$(brew --prefix zlib) \ + -DCMAKE_BUILD_TYPE=Release \ + -DFIND_BOOST_USE_CONFIG=OFF \ + .. + make -j8 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-macos + path: | + build/i2pd + build/vain + build/keygen + build/keyinfo + build/famtool + build/routerinfo + build/regaddr + build/regaddr_3ld + build/i2pbase64 + build/offlinekeys + build/b33address + build/regaddralias + build/x25519 + build/verifyhost + build/autoconf_i2pd + + build-macos-legacy: + name: Build macOS Legacy with UPnP ON + runs-on: macos-13 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: Install dependencies + run: | + brew update + brew install boost miniupnpc openssl@1.1 zlib + + - name: Configure and build with CMake + run: | + mkdir build + cd build + cmake \ + -DWITH_UPNP=ON \ + -DOPENSSL_ROOT_DIR="/opt/homebrew/opt/openssl@1.1" \ + -DBOOST_ROOT="/opt/homebrew/opt/boost" \ + -DCMAKE_PREFIX_PATH="/opt/homebrew/opt/boost;/opt/homebrew/opt/miniupnpc;/opt/homebrew/opt/openssl@1.1" \ + -DZLIB_ROOT=$(brew --prefix zlib) \ + -DCMAKE_BUILD_TYPE=Release \ + -DFIND_BOOST_USE_CONFIG=OFF \ + .. + make -j8 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-macos-legacy + path: | + build/i2pd + build/vain + build/keygen + build/keyinfo + build/famtool + build/routerinfo + build/regaddr + build/regaddr_3ld + build/i2pbase64 + build/offlinekeys + build/b33address + build/regaddralias + build/x25519 + build/verifyhost + build/autoconf_i2pd + + build-freebsd: + name: Build FreeBSD with UPnP ON + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: true + + - name: Test in FreeBSD + id: test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + mem: 2048 + sync: rsync + copyback: true + prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc + run: | + mkdir build + cd build + cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .. + gmake -j2 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-freebsd + path: | + build/i2pd + build/vain + build/keygen + build/keyinfo + build/famtool + build/routerinfo + build/regaddr + build/regaddr_3ld + build/i2pbase64 + build/offlinekeys + build/b33address + build/regaddralias + build/x25519 + build/verifyhost + build/autoconf_i2pd + + build-windows-ucrt: + name: Build Windows UCRT x64 + runs-on: windows-latest + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: true + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: UCRT64 + install: base-devel git mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-gcc mingw-w64-ucrt-x86_64-boost mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-miniupnpc + update: true + + - name: Build application + run: | + cmake -DWITH_GIT_VERSION=ON -DWITH_STATIC=ON -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . + cmake --build . -- -j3 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-windows-ucrt + path: | + ./i2pd.exe + ./vain.exe + ./keygen.exe + ./keyinfo.exe + ./famtool.exe + ./routerinfo.exe + ./regaddr.exe + ./regaddr_3ld.exe + ./i2pbase64.exe + ./offlinekeys.exe + ./b33address.exe + ./regaddralias.exe + ./x25519.exe + ./verifyhost.exe + ./autoconf_i2pd.exe + + build-windows-arm: + name: Build Windows ARM64 + runs-on: windows-11-arm + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: true + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: CLANGARM64 + install: base-devel git mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-ninja mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-boost mingw-w64-clang-aarch64-openssl mingw-w64-clang-aarch64-miniupnpc + update: true + + - name: Build application + run: | + cmake -DWITH_GIT_VERSION=ON -DWITH_STATIC=ON -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . + cmake --build . -- -j3 + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: i2pd-windows-arm64 + path: | + ./i2pd.exe + ./vain.exe + ./keygen.exe + ./keyinfo.exe + ./famtool.exe + ./routerinfo.exe + ./regaddr.exe + ./regaddr_3ld.exe + ./i2pbase64.exe + ./offlinekeys.exe + ./b33address.exe + ./regaddralias.exe + ./x25519.exe + ./verifyhost.exe + ./autoconf_i2pd.exe + + release: + name: Create Continuous Release + runs-on: ubuntu-latest + needs: [build-linux, build-macos, build-macos-legacy, build-freebsd, build-windows-ucrt, build-windows-arm] + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: List downloaded artifacts + run: | + echo "Downloaded artifacts:" + if [ -d "artifacts" ]; then + find artifacts -type f + echo "" + echo "Artifact directories:" + ls -la artifacts/ + else + echo "No artifacts directory found" + fi + + - name: Create release directory structure + run: | + mkdir -p releases/{linux,freebsd,macos,windows} + + - name: Organize Linux artifacts + run: | + # Find and copy Linux artifacts (Ubuntu/CMake builds) + if [ -d "artifacts/i2pd-ubuntu" ]; then + cp -r "artifacts/i2pd-ubuntu" "releases/linux/ubuntu" + echo "Copied Linux artifact: ubuntu" + + # Create compressed archive for Linux build + tar -czf "i2pd-linux-ubuntu.tar.gz" -C releases/linux/ubuntu . + echo "Created Linux archive: i2pd-linux-ubuntu.tar.gz" + else + echo "No Linux artifacts found" + fi + + - name: Organize FreeBSD artifacts + run: | + # Copy FreeBSD artifacts + if [ -d "artifacts/i2pd-freebsd" ]; then + cp -r "artifacts/i2pd-freebsd" releases/freebsd/ + echo "Copied FreeBSD artifacts" + + # Create compressed archive for FreeBSD + tar -czf i2pd-freebsd.tar.gz -C releases/freebsd i2pd-freebsd + echo "Created FreeBSD archive: i2pd-freebsd.tar.gz" + else + echo "No FreeBSD artifacts found" + fi + + - name: Organize macOS artifacts + run: | + # Find and copy macOS (ARM) artifacts + if [ -d "artifacts/i2pd-macos" ]; then + cp -r "artifacts/i2pd-macos" "releases/macos/macos-arm" + echo "Copied macOS ARM artifact" + + # Create compressed archive for macOS ARM build + tar -czf "i2pd-macos-arm.tar.gz" -C releases/macos/macos-arm . + echo "Created macOS ARM archive: i2pd-macos-arm.tar.gz" + else + echo "No macOS ARM artifacts found" + fi + + # Find and copy macOS (Legacy/Intel) artifacts + if [ -d "artifacts/i2pd-macos-legacy" ]; then + cp -r "artifacts/i2pd-macos-legacy" "releases/macos/macos-legacy" + echo "Copied macOS Legacy artifact" + + # Create compressed archive for macOS Legacy build + tar -czf "i2pd-macos-legacy.tar.gz" -C releases/macos/macos-legacy . + echo "Created macOS Legacy archive: i2pd-macos-legacy.tar.gz" + else + echo "No macOS Legacy artifacts found" + fi + + - name: Organize Windows artifacts + run: | + # Find and copy Windows UCRT (x64) artifact + if [ -d "artifacts/i2pd-windows-ucrt" ]; then + echo "Processing Windows UCRT (x64) artifact" + # Create releases/windows/ucrt directory and copy .exe files directly to it + mkdir -p "releases/windows/ucrt" + cp "artifacts/i2pd-windows-ucrt"/*.exe "releases/windows/ucrt/" 2>/dev/null || echo "No .exe files in Windows UCRT artifact or copying failed" + + # Create ZIP archive for Windows UCRT build + if ls "releases/windows/ucrt"/*.exe >/dev/null 2>&1; then + cd "releases/windows/ucrt" + zip -r "../../../i2pd-windows-ucrt.zip" *.exe + cd ../../.. + echo "Created Windows UCRT archive: i2pd-windows-ucrt.zip" + else + echo "No .exe files found in Windows UCRT release directory" + ls -la "releases/windows/ucrt/" 2>/dev/null || echo "Windows UCRT release directory doesn't exist" + fi + else + echo "No Windows UCRT artifacts found" + fi + + # Find and copy Windows ARM64 artifact + if [ -d "artifacts/i2pd-windows-arm64" ]; then + echo "Processing Windows ARM64 artifact" + # Create releases/windows/arm64 directory and copy .exe files directly to it + mkdir -p "releases/windows/arm64" + cp "artifacts/i2pd-windows-arm64"/*.exe "releases/windows/arm64/" 2>/dev/null || echo "No .exe files in Windows ARM64 artifact or copying failed" + + # Create ZIP archive for Windows ARM64 build + if ls "releases/windows/arm64"/*.exe >/dev/null 2>&1; then + cd "releases/windows/arm64" + zip -r "../../../i2pd-windows-arm64.zip" *.exe + cd ../../.. + echo "Created Windows ARM64 archive: i2pd-windows-arm64.zip" + else + echo "No .exe files found in Windows ARM64 release directory" + ls -la "releases/windows/arm64/" 2>/dev/null || echo "Windows ARM64 release directory doesn't exist" + fi + else + echo "No Windows ARM64 artifacts found" + fi + + - name: Prepare release assets + run: | + echo "Listing all release assets:" + ls -la *.tar.gz *.zip 2>/dev/null || echo "No release assets found - will create them from available artifacts" + + - name: Delete previous continuous release assets + run: | + # Get the release ID for the continuous release + RELEASE_ID=$(gh api repos/${{ github.repository }}/releases/tags/continuous --jq '.id' 2>/dev/null || echo "notfound") + if [ "$RELEASE_ID" != "notfound" ] && [ "$RELEASE_ID" != "" ]; then + echo "Found existing continuous release with ID: $RELEASE_ID" + # Get asset IDs and delete them + ASSET_IDS=$(gh api repos/${{ github.repository }}/releases/$RELEASE_ID/assets --jq '.[].id') + for asset_id in $ASSET_IDS; do + if [ ! -z "$asset_id" ]; then + echo "Deleting asset ID: $asset_id" + gh api -X DELETE repos/${{ github.repository }}/releases/assets/$asset_id || true + fi + done + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true + + - name: Final listing of assets + run: | + echo "Final check for release assets:" + ls -la *.tar.gz *.zip 2>/dev/null || echo "No assets to upload - check if artifacts were processed" + + - name: Update or Create Continuous Release + id: create_release + uses: softprops/action-gh-release@v2 + with: + tag_name: continuous + name: Continuous Release + body: | + Continuous Release Build + + Latest Workflow Run: ${{ github.run_id }} + Commit: ${{ github.sha }} + Updated: $(date -u) + + This release contains build artifacts for multiple platforms: + - Linux (with UPnP ON) + - FreeBSD (with UPnP ON) + - macOS (ARM with UPnP ON) + - macOS (Legacy/Intel with UPnP ON) + - Windows (UCRT x64 variant) + - Windows (ARM64 variant) + + Artifacts include the main executable and all associated utilities. + This release is continuously updated with the latest builds. + draft: false + prerelease: true + make_latest: false + files: | + *.tar.gz + *.zip + fail_on_unmatched_files: false diff --git a/.gitignore b/.gitignore index 38d6a5d..83870eb 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ offlinekeys regaddr_3ld verifyhost x25519 +autoconf_i2pd *.exe # private key files diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f469526 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,423 @@ +cmake_minimum_required(VERSION 3.7) + + +if(${CMAKE_VERSION} VERSION_LESS 3.22) + cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) +else() + cmake_policy(VERSION 3.22) +endif() + +# for debugging +#set(CMAKE_VERBOSE_MAKEFILE on) + +# paths +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/i2pd/build/cmake_modules") +set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/i2pd") + +set(LIBI2PD_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd) +set(LIBI2PD_CLIENT_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd_client) +set(LANG_SRC_DIR ${CMAKE_SOURCE_DIR}/i18n) +set(DAEMON_SRC_DIR ${CMAKE_SOURCE_DIR}/daemon) +set(I2PD_TOOLS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +include(Version) +set_version("${LIBI2PD_SRC_DIR}/version.h" PROJECT_VERSION) + +project( + i2pd + VERSION ${PROJECT_VERSION} + HOMEPAGE_URL "https://i2pd.website/" + LANGUAGES C CXX +) + +# configurable options +option(WITH_HARDENING "Use hardening compiler flags" OFF) +option(WITH_LIBRARY "Build library" ON) +option(WITH_BINARY "Build binary" ON) +option(WITH_STATIC "Static build" OFF) +option(WITH_UPNP "Include support for UPnP client" OFF) +option(WITH_GIT_VERSION "Use git commit info as version" OFF) +option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) +option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) +option(BUILD_TESTING "Build tests" OFF) + +IF(BUILD_TESTING) + enable_testing() +ENDIF() + +# Handle paths nicely +include(GNUInstallDirs) + +# Architecture +include(TargetArch) +target_architecture(ARCHITECTURE) + +include(CheckAtomic) + +if(WITH_STATIC) + if(MSVC) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif() +endif() + +include_directories(${LIBI2PD_SRC_DIR}) +FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp) +add_library(libi2pd ${LIBI2PD_SRC}) +set_target_properties(libi2pd PROPERTIES PREFIX "") + +if(WITH_LIBRARY) + install(TARGETS libi2pd + EXPORT libi2pd + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Libraries) +endif() + +include_directories(${LIBI2PD_CLIENT_SRC_DIR}) +FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp) +add_library(libi2pdclient ${CLIENT_SRC}) +set_target_properties(libi2pdclient PROPERTIES PREFIX "") + +if(WITH_LIBRARY) + install(TARGETS libi2pdclient + EXPORT libi2pdclient + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Libraries) +endif() + +include_directories(${LANG_SRC_DIR}) +FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp) +add_library(libi2pdlang ${LANG_SRC}) +set_target_properties(libi2pdlang PROPERTIES PREFIX "") + +if(WITH_LIBRARY) + install(TARGETS libi2pdlang + EXPORT libi2pdlang + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Libraries) +endif() + +include_directories(${DAEMON_SRC_DIR}) + +set(DAEMON_SRC + "${DAEMON_SRC_DIR}/Daemon.cpp" + "${DAEMON_SRC_DIR}/HTTPServer.cpp" + "${DAEMON_SRC_DIR}/I2PControl.cpp" + "${DAEMON_SRC_DIR}/I2PControlHandlers.cpp" + "${DAEMON_SRC_DIR}/i2pd.cpp" + "${DAEMON_SRC_DIR}/UPnP.cpp" +) + +if(WIN32) + set(WIN32_SRC_DIR ${CMAKE_SOURCE_DIR}/Win32) + include_directories(${WIN32_SRC_DIR}) + + list(APPEND DAEMON_SRC + "${WIN32_SRC_DIR}/DaemonWin32.cpp" + "${WIN32_SRC_DIR}/Win32App.cpp" + "${WIN32_SRC_DIR}/Win32Service.cpp" + "${WIN32_SRC_DIR}/Win32NetState.cpp" + ) + + file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX") + +endif() + +if(WITH_UPNP) + add_definitions(-DUSE_UPNP) +endif() + +if(WITH_GIT_VERSION) + include(GetGitRevisionDescription) + git_describe(GIT_VERSION) + add_definitions(-DGITVER=${GIT_VERSION}) +endif() + +if(APPLE) + add_definitions(-DMAC_OSX) +endif() + +if(HAIKU) + add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE) +endif() + +if(MSVC) + add_definitions(-DWINVER=0x0600) + add_definitions(-D_WIN32_WINNT=0x0600) +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic") + # TODO: The following is incompatible with static build and enabled hardening for OpenWRT. + # Multiple definitions of __stack_chk_fail(libssp & libc) + if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s") + endif() + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections") + set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") + if(WITH_HARDENING) + add_definitions("-D_FORTIFY_SOURCE=2") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat -Wformat-security -Werror=format-security") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector --param ssp-buffer-size=4") + endif() +elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # more tweaks + if(LINUX) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -stdlib=libstdc++") # required for + list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++") # required to link with -stdlib=libstdc++ + endif() + if(NOT APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions") + endif() +endif() + +# compiler flags customization(by system) +if(UNIX) + list(APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp") + if(NOT(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE)) + # "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8 + add_definitions("-D_GLIBCXX_USE_NANOSLEEP=1") + endif() +endif() + +if(WITH_ADDRSANITIZER) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address") +endif() + +if(WITH_THREADSANITIZER) + if(WITH_ADDRSANITIZER) + message(FATAL_ERROR "thread sanitizer option cannot be combined with address sanitizer") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") + endif() +endif() + +if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0 AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0) # gcc 8-9 + list(APPEND CMAKE_REQUIRED_LIBRARIES "stdc++fs") +endif() + +# Use std::atomic instead of GCC builtins on macOS PowerPC: +# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111 +# This has been fixed in Boost 1.81, nevertheless we retain the setting for the sake of compatibility. +if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc") + add_definitions(-DBOOST_SP_USE_STD_ATOMIC) +endif() + +# libraries +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + +if(WITH_STATIC) + if(NOT MSVC) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + endif() + + set(Boost_USE_STATIC_LIBS ON) + if(MSVC) + set(Boost_USE_STATIC_RUNTIME ON) + else() + set(Boost_USE_STATIC_RUNTIME OFF) + endif() + + if(MSVC) + set(OPENSSL_MSVC_STATIC_RT ON) + endif() + set(OPENSSL_USE_STATIC_LIBS ON) + + set(ZLIB_USE_STATIC_LIBS ON) + if(MSVC) + set(ZLIB_NAMES zlibstatic zlibstat) + else() + set(ZLIB_NAMES libz zlibstatic zlibstat zlib z) + endif() + + if(WITH_UPNP) + set(MINIUPNPC_USE_STATIC_LIBS ON) + add_definitions(-DMINIUPNP_STATICLIB) + endif() + + set(BUILD_SHARED_LIBS OFF) + + if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") + # set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") + set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,-u,pthread_create,-u,pthread_once,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_join,-u,pthread_equal,-u,pthread_detach,-u,pthread_cond_wait,-u,pthread_cond_signal,-u,pthread_cond_destroy,-u,pthread_cond_broadcast,-u,pthread_cancel") + endif() +else() + # TODO: Consider separate compilation for LIBI2PD_SRC for library. + # No need in -fPIC overhead for binary if not interested in library + # HINT: revert c266cff CMakeLists.txt: compilation speed up + if(NOT MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + endif() + add_definitions(-DBOOST_ATOMIC_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK) + if(WIN32) + set(Boost_USE_STATIC_LIBS OFF) + set(Boost_USE_STATIC_RUNTIME OFF) + endif() +endif() + +find_package(Boost REQUIRED COMPONENTS filesystem program_options) +if(NOT DEFINED Boost_FOUND) + message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") +endif() + +find_package(OpenSSL REQUIRED) +if(NOT DEFINED OPENSSL_FOUND) + message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!") +endif() + +if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0") + add_definitions(-DOPENSSL_SUPPRESS_DEPRECATED) +endif() + +if(WITH_UPNP) + find_package(MiniUPnPc REQUIRED) + if(NOT MINIUPNPC_FOUND) + message(SEND_ERROR "Could not find MiniUPnPc. Please download and install it first!") + else() + include_directories(SYSTEM ${MINIUPNPC_INCLUDE_DIR}) + endif() +endif() + +find_package(ZLIB) +if(ZLIB_FOUND) + link_directories(${ZLIB_ROOT}/lib) +endif() + +# C++ standard to use, based on compiler and version of boost +if(NOT MSVC) +# check for c++20 & c++17 support + include(CheckCXXCompilerFlag) + + if(Boost_VERSION VERSION_GREATER_EQUAL "1.83") # min boost version for c++20 + CHECK_CXX_COMPILER_FLAG("-std=c++20" CXX20_SUPPORTED) + endif() + CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) + + + if(CXX20_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") + elseif(CXX17_SUPPORTED) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + else() + message(SEND_ERROR "C++20 nor C++17 standard not seems to be supported by compiler. Too old version?") + endif() +endif() + +# load includes +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) + +# show summary +message(STATUS "---------------------------------------") +message(STATUS "Build type : ${CMAKE_BUILD_TYPE}") +message(STATUS "Compiler vendor : ${CMAKE_CXX_COMPILER_ID}") +message(STATUS "Compiler version : ${CMAKE_CXX_COMPILER_VERSION}") +message(STATUS "Compiler path : ${CMAKE_CXX_COMPILER}") +message(STATUS "Architecture : ${ARCHITECTURE}") +message(STATUS "Compiler flags : ${CMAKE_CXX_FLAGS}") +message(STATUS "Install prefix: : ${CMAKE_INSTALL_PREFIX}") +message(STATUS "Options:") +message(STATUS " HARDENING : ${WITH_HARDENING}") +message(STATUS " LIBRARY : ${WITH_LIBRARY}") +message(STATUS " BINARY : ${WITH_BINARY}") +message(STATUS " STATIC BUILD : ${WITH_STATIC}") +message(STATUS " UPnP : ${WITH_UPNP}") +if(WITH_GIT_VERSION) +message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})") +else() +message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}") +endif() +message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}") +message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}") +message(STATUS "---------------------------------------") + +if(WITH_BINARY) + if(WIN32) + add_executable("${PROJECT_NAME}" WIN32 ${DAEMON_SRC} ${WIN32_RC}) + else() + add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) + endif() + + if(WIN32) + list(APPEND MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi") + # OpenSSL may require Crypt32 library on MSVC build, which is not added by CMake lesser than 3.21 + if(MSVC AND ${CMAKE_VERSION} VERSION_LESS 3.21) + list(APPEND MINGW_EXTRA "crypt32") + endif() + endif() + + if(WITH_STATIC) + if(NOT MSVC) + set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") + endif() + endif() + + if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now") + endif() + + # FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04 + list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES) + if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*") + list(REMOVE_AT Boost_LIBRARIES -1) + endif() + + # synchronization library is incompatible with Windows 7 + if(WIN32) + get_target_property(BOOSTFSLIBS Boost::filesystem INTERFACE_LINK_LIBRARIES) + list(REMOVE_ITEM BOOSTFSLIBS synchronization) + set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}") + endif() + + if(WITH_STATIC) + set(DL_LIB ${CMAKE_DL_LIBS}) + endif() + + target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + + install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) + set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") + set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin") +endif() + +if(BUILD_TESTING) + add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests) +endif() + +set(TOOLS + vain + keygen + keyinfo + famtool + routerinfo + regaddr + regaddr_3ld + i2pbase64 + offlinekeys + b33address + regaddralias + x25519 + verifyhost + autoconf_i2pd +) + +foreach(tool IN LISTS TOOLS) + add_executable(${tool} ${I2PD_TOOLS_DIR}/${tool}.cpp) + add_dependencies(${tool} libi2pd) + + target_link_libraries(${tool} libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) + + # routerinfo and famtool want -latomic on Linux/FreeBSD + #if((IS_LINUX OR IS_FREEBSD) AND (${tool} STREQUAL "routerinfo" OR ${tool} STREQUAL "famtool")) + # target_link_libraries(${tool} atomic) + #endif() +endforeach() diff --git a/Makefile b/Makefile index a621a07..ab9d3b3 100755 --- a/Makefile +++ b/Makefile @@ -1,59 +1,64 @@ -UNAME = $(shell uname -s) +UNAME := $(shell uname -s) -I2PD_PATH = i2pd -I2PD_LIB = libi2pd.a +I2PD_PATH := i2pd +I2PD_LIB := libi2pd.a -LIBI2PD_PATH = $(I2PD_PATH)/libi2pd -LIBI2PD_CLIENT_PATH = $(I2PD_PATH)/libi2pd_client +LIBI2PD_PATH := $(I2PD_PATH)/libi2pd +LIBI2PD_CLIENT_PATH := $(I2PD_PATH)/libi2pd_client CXX ?= g++ -CXXFLAGS = -Wall -std=c++17 -O2 -INCFLAGS = -I$(LIBI2PD_PATH) -I$(LIBI2PD_CLIENT_PATH) -DEFINES = -DOPENSSL_SUPPRESS_DEPRECATED - -LDFLAGS = -LDLIBS = $(I2PD_PATH)/$(I2PD_LIB) -lboost_system$(BOOST_SUFFIX) -lboost_program_options$(BOOST_SUFFIX) -lssl -lcrypto -lz +CXXFLAGS := -Wall -std=c++17 -O2 +INCFLAGS := -I$(LIBI2PD_PATH) -I$(LIBI2PD_CLIENT_PATH) +DEFINES := -DOPENSSL_SUPPRESS_DEPRECATED +LDFLAGS := +LDLIBS := $(I2PD_PATH)/$(I2PD_LIB) -lboost_program_options$(BOOST_SUFFIX) -lssl -lcrypto -lz ifeq ($(UNAME),Linux) - CXXFLAGS += -g + CXXFLAGS += -g + LDLIBS += -lrt -lpthread else ifeq ($(UNAME),Darwin) - CXXFLAGS += -g + CXXFLAGS += -g + LDLIBS += -lpthread + + ifeq ($(shell test -d /opt/homebrew && echo "true"),true) + BREW_PREFIX := /opt/homebrew + else + BREW_PREFIX := /usr/local + endif + + INCFLAGS += -I$(BREW_PREFIX)/include -I$(BREW_PREFIX)/opt/openssl@3/include + LDFLAGS += -L$(BREW_PREFIX)/lib -L$(BREW_PREFIX)/opt/openssl@3/lib + + LDLIBS += -lboost_program_options else ifeq ($(UNAME),FreeBSD) - CXXFLAGS += -g + CXXFLAGS += -g + LDLIBS += -lthr -lpthread + LDFLAGS += -L/usr/local/lib + INCFLAGS += -I/usr/local/include else -# Win32 - CXXFLAGS += -Os -fPIC -msse - DEFINES += -DWIN32_LEAN_AND_MEAN - BOOST_SUFFIX = -mt + # Windows + CXXFLAGS += -Os -fPIC -msse + DEFINES += -DWIN32_LEAN_AND_MEAN + LDFLAGS += -L/clang64/lib + INCFLAGS += -I/clang64/include + BOOST_SUFFIX = + LDLIBS += -lwsock32 -lws2_32 -liphlpapi -lpthread endif -ifeq ($(UNAME),Linux) - LDLIBS += -lrt -lpthread -else ifeq ($(UNAME),Darwin) - LDLIBS += -lpthread - LDFLAGS += -L/usr/local/opt/openssl@1.1/lib -L/usr/local/lib - INCFLAGS += -I/usr/local/opt/openssl@1.1/include -I/usr/local/include -else ifeq ($(UNAME),FreeBSD) - LDLIBS += -lthr -lpthread - LDFLAGS += -L/usr/local/lib - INCFLAGS += -I/usr/local/include -else -# Win32 - LDLIBS += -lwsock32 -lws2_32 -liphlpapi -lpthread - LDFLAGS += -s -static -endif +# ------------------------- +# Targets +# ------------------------- +all: $(I2PD_LIB) vain keygen keyinfo famtool routerinfo regaddr regaddr_3ld i2pbase64 offlinekeys b33address regaddralias x25519 verifyhost autoconf_i2pd - -all: $(I2PD_LIB) vain keygen keyinfo famtool routerinfo regaddr regaddr_3ld i2pbase64 offlinekeys b33address regaddralias x25519 verifyhost autoconf -vain: vain.o $(I2PD_LIB) +vain: vain.o $(I2PD_LIB) $(CXX) -o vain $(LDFLAGS) vain.o $(LDLIBS) -autoconf: autoconf.o $(I2PD_LIB) - $(CXX) -o autoconf $(DEFINES) $(LDFLAGS) autoconf.o $(LDLIBS) +autoconf_i2pd: autoconf_i2pd.o $(I2PD_LIB) + $(CXX) -o autoconf_i2pd $(DEFINES) $(LDFLAGS) autoconf_i2pd.o $(LDLIBS) routerinfo: routerinfo.o $(I2PD_LIB) - $(CXX) -o routerinfo $(LDFLAGS) routerinfo.o $(LDLIBS) -latomic + $(CXX) -o routerinfo $(LDFLAGS) routerinfo.o $(LDLIBS) keygen: keygen.o $(I2PD_LIB) $(CXX) -o keygen $(DEFINES) $(LDFLAGS) keygen.o $(LDLIBS) @@ -62,7 +67,7 @@ keyinfo: keyinfo.o $(I2PD_LIB) $(CXX) -o keyinfo $(DEFINES) $(LDFLAGS) keyinfo.o $(LDLIBS) famtool: famtool.o $(I2PD_LIB) - $(CXX) -o famtool $(DEFINES) $(LDFLAGS) famtool.o $(LDLIBS) -latomic + $(CXX) -o famtool $(DEFINES) $(LDFLAGS) famtool.o $(LDLIBS) regaddr: regaddr.o $(I2PD_LIB) $(CXX) -o regaddr $(DEFINES) $(LDFLAGS) regaddr.o $(LDLIBS) @@ -88,7 +93,9 @@ x25519: x25519.o $(I2PD_LIB) verifyhost: verifyhost.o $(I2PD_LIB) $(CXX) -o verifyhost $(DEFINES) $(LDFLAGS) verifyhost.o $(LDLIBS) -.SUFFIXES: +# ------------------------- +# Object compilation +# ------------------------- .SUFFIXES: .c .cc .C .cpp .o $(I2PD_LIB): @@ -97,6 +104,9 @@ $(I2PD_LIB): %.o: %.cpp $(I2PD_LIB) $(CXX) $(CXXFLAGS) $(DEFINES) $(INCFLAGS) -c -o $@ $< +# ------------------------- +# Cleanup +# ------------------------- count: wc *.c *.cc *.C *.cpp *.h *.hpp @@ -105,17 +115,18 @@ clean-i2pd: clean-obj: rm -f $(wildcard *.o) + stripall: - strip b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo x25519 verifyhost vain autoconf + strip b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo x25519 verifyhost vain autoconf_i2pd + +builddir: + mkdir -p build + mv b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo x25519 verifyhost vain autoconf_i2pd build/ || true clean-bin: - rm -f b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo x25519 verifyhost vain autoconf + rm -f b33address famtool i2pbase64 keygen keyinfo offlinekeys regaddr regaddr_3ld regaddralias routerinfo x25519 verifyhost vain autoconf_i2pd clean: clean-i2pd clean-obj clean-bin -.PHONY: all -.PHONY: count -.PHONY: clean-i2pd -.PHONY: clean-obj -.PHONY: clean-bin -.PHONY: clean +.PHONY: all count clean-i2pd clean-obj clean-bin clean + diff --git a/README.md b/README.md index 038b35e..183d85a 100755 --- a/README.md +++ b/README.md @@ -31,6 +31,9 @@ git submodule init && git submodule update git submodule update --init git pull --recurse-submodules make +# optional, for small output +# make stripall +# make builddir ``` ## Tools included diff --git a/autoconf.cpp b/autoconf_i2pd.cpp similarity index 100% rename from autoconf.cpp rename to autoconf_i2pd.cpp