From febf23f4be7f5d2e6e072607c60a5d11fdfdc173 Mon Sep 17 00:00:00 2001 From: Lunar Date: Thu, 16 Oct 2025 21:43:45 +1000 Subject: [PATCH] add build workflows (thank flu) --- .github/workflows/build-and-release.yml | 492 ++++++++++++++++++++++++ .github/workflows/build.yml | 93 ----- CMakeLists.txt | 423 ++++++++++++++++++++ 3 files changed, 915 insertions(+), 93 deletions(-) create mode 100644 .github/workflows/build-and-release.yml delete mode 100644 .github/workflows/build.yml create mode 100644 CMakeLists.txt diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml new file mode 100644 index 0000000..9433a13 --- /dev/null +++ b/.github/workflows/build-and-release.yml @@ -0,0 +1,492 @@ +name: Build All Platforms and Release + +on: + push: + branches: + - '*' + 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 + + 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 + + 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 + + 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 + + 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.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.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/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 855dc60..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Build and Cross-compile - -on: - push: - branches: - - main - - master - tags: - - 'v*' - -jobs: - build: - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - compiler: [clang] - - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout Repository - uses: actions/checkout@v3 - with: - submodules: true - - ####################### - # Ubuntu dependencies # - ####################### - - name: Install dependencies (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - sudo apt update - sudo apt install --no-install-recommends -y build-essential libboost-all-dev libssl-dev git - - ####################### - # macOS dependencies # - #BY VADE = https://github.com/MetanoicArmor - ####################### - - name: Install dependencies (macOS) - if: matrix.os == 'macos-latest' - run: | - brew update - brew install boost openssl@3 cmake make - - ####################### - # Windows dependencies # - ####################### -# - name: Install MSYS2 (Windows) -# if: matrix.os == 'windows-latest' -## uses: msys2/setup-msys2@v2 - # with: - # msystem: CLANG64 - # install: base-devel git mingw-w64-x86_64-clang mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-miniupnpc - # update: true - - - name: Initialize Git Submodules - run: git submodule update --init --recursive - - ####################### - # Build Project - ####################### - - name: Build Project (Ubuntu) - if: matrix.os == 'ubuntu-latest' - run: | - make -j$(nproc) - make stripall - make builddir - - - name: Build Project (macOS) - if: matrix.os == 'macos-latest' - run: | - make HOMEBREW=1 -j8 - make stripall - make builddir - -# - name: Build Project (Windows) -# if: matrix.os == 'windows-latest' -## shell: msys2 {0} - # run: | - # cd "${GITHUB_WORKSPACE}" - # make -j$(nproc) - # make stripall - # make builddir - - ####################### - # Upload binaries - ####################### - - name: Upload binaries - uses: actions/upload-artifact@v4 - with: - name: my-binaries-${{ matrix.os }} - path: build/* - diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7bfbbb9 --- /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 +) + +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()