From 4036d299eb0d204f6b7567b39a334d67372051a8 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 11 Jan 2021 00:40:17 +0100 Subject: [PATCH] Windows: reproducible builds --- BUILDING.md | 22 ++- CMakeLists.txt | 6 +- Dockerfile.windows | 169 +++++++++++++++++++ Dockerfile_windows => Dockerfile.windows_mxe | 0 Makefile | 6 +- cmake/FindQREncode.cmake | 3 + src/CMakeLists.txt | 4 +- 7 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 Dockerfile.windows rename Dockerfile_windows => Dockerfile.windows_mxe (100%) diff --git a/BUILDING.md b/BUILDING.md index 6b4fb74..1be8608 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -22,7 +22,7 @@ git clone --branch master --recursive https://git.wownero.com/feather/feather.gi cd feather ``` -Replace `master` with the desired version tag (e.g. `beta-1`) to build the release binary. +Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary. #### 2. Base image @@ -48,37 +48,35 @@ Hashes for tagged commits should match: beta-1: d1a52e3bac1abbae4adda1fc88cb2a7a06fbd61085868421897c6a4f3f4eb091 feather ``` -### Windows - -The docker image for Windows static compiles uses Ubuntu 18.04 and installs [mxe](https://mxe.cc) from [our git](https://git.wownero.com/feather/mxe/src/branch/feather-patch), -which comes with: OpenSSL 1.1.1g, Qt 5.15.0 (OpenGL via mesa). For more information, check the Dockerfile: `Dockerfile_windows`. +### Windows (reproducible) #### 1. Clone ```bash -git clone --recursive https://git.wownero.com/feather/feather.git +git clone --branch master --recursive https://git.wownero.com/feather/feather.git cd feather ``` +Replace `master` with the desired version tag (e.g. `beta-4`) to build the release binary. + #### 2. Base image -Warning: Building the MXE base image takes up to a hour, so go watch a movie. ```bash -docker build -f Dockerfile_windows --tag feather:win --build-arg THREADS=8 . +docker build -f Dockerfile.windows --tag feather:win --build-arg THREADS=4 . ``` -Note: You only need to build the base image once. +Building the base image takes a while. You only need to build the base image once. #### 3. Build ```bash -docker run --rm -it -v /tmp/ccache:/root/.ccache -v PATH_TO_FEATHER:/feather -w /feather feather:win /bin/bash -c 'PATH="/mxe/usr/bin/:$PATH" TOR_BIN="/mxe/usr/x86_64-w64-mingw32.static/bin/tor.exe" make windows-mxe-release -j8' +docker run --rm -it -v $PWD:/feather -w /feather feather:win sh -c 'TOR_BIN="/usr/local/tor/bin/tor.exe" make depends root=/depends target=x86_64-w64-mingw32 tag=win-x64 -j4' ``` -Replace `PATH_TO_FEATHER` with the absolute path to Feather locally. +If you're re-running a build make sure to `rm -rf build/` first. -The resulting binary can be found in `build/bin/feather.exe`. +The resulting binary can be found in `build/x86_64-w64-mingw32/release/bin/feather.exe`. ## macOS diff --git a/CMakeLists.txt b/CMakeLists.txt index 551a821..1fd3b08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ if(STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ${CMAKE_FIND_LIBRARY_SUFFIXES}) add_definitions(-DMONERO_GUI_STATIC) endif() @@ -147,6 +148,9 @@ endif() if(APPLE AND NOT BOOST_ROOT) execute_process(COMMAND brew --prefix boost OUTPUT_VARIABLE BOOST_ROOT OUTPUT_STRIP_TRAILING_WHITESPACE) endif() +if(MINGW) + set(Boost_THREADAPI win32) +endif() find_package(Boost 1.58 REQUIRED COMPONENTS system filesystem @@ -223,7 +227,7 @@ if(MINGW) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj") set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt) if(DEPENDS) - set(ICU_LIBRARIES icuio icui18n icuuc icudata icutu iconv) + set(ICU_LIBRARIES iconv) else() set(ICU_LIBRARIES icuio icuin icuuc icudt icutu iconv) endif() diff --git a/Dockerfile.windows b/Dockerfile.windows new file mode 100644 index 0000000..c6713d7 --- /dev/null +++ b/Dockerfile.windows @@ -0,0 +1,169 @@ +FROM ubuntu:20.04 + +ARG THREADS=1 +ARG QT_VERSION=5.15.2 +ENV SOURCE_DATE_EPOCH=1397818193 + +RUN apt update && \ + DEBIAN_FRONTEND=noninteractive apt install -y curl wget zip automake build-essential cmake gcc-mingw-w64 g++-mingw-w64 gettext git libtool pkg-config \ + python && \ + rm -rf /var/lib/apt/lists/* + +RUN update-alternatives --set x86_64-w64-mingw32-g++ $(which x86_64-w64-mingw32-g++-posix) && \ + update-alternatives --set x86_64-w64-mingw32-gcc $(which x86_64-w64-mingw32-gcc-posix) + +RUN git clone -b v0.17.1.9 --depth 1 https://github.com/monero-project/monero && \ + cd monero && \ + git reset --hard 8fef32e45c80aec41f25be9d1d8fb75adc883c64 && \ + cp -a contrib/depends / && \ + cd .. && \ + rm -rf monero + +RUN make -j$THREADS -C /depends HOST=x86_64-w64-mingw32 NO_QT=1 + +RUN git clone git://code.qt.io/qt/qt5.git -b ${QT_VERSION} --depth 1 && \ + cd qt5 && \ + git clone git://code.qt.io/qt/qtbase.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtimageformats.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtmultimedia.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtsvg.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qttools.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qttranslations.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtxmlpatterns.git -b ${QT_VERSION} --depth 1 && \ + git clone git://code.qt.io/qt/qtwebsockets.git -b ${QT_VERSION} --depth 1 && \ + OPENSSL_LIBS="-lssl -lcrypto -lpthread -ldl" \ + ./configure --prefix=/depends/x86_64-w64-mingw32 -xplatform win32-g++ \ + -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \ + -I $(pwd)/qtbase/src/3rdparty/angle/include \ + -opensource -confirm-license -release -static -static-runtime -no-opengl \ + -no-avx -openssl -I /depends/x86_64-w64-mingw32/include -L /depends/x86_64-w64-mingw32/lib \ + -qt-freetype -qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \ + -skip gamepad -skip location -skip qt3d -skip qtactiveqt -skip qtandroidextras \ + -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d -skip qtdoc \ + -skip qtgamepad -skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing \ + -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport \ + -skip qtspeech -skip qttools -skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel \ + -skip qtwebengine -skip qtwebview -skip qtwinextras -skip qtx11extras \ + -skip qtdeclarative -skip qtquickcontrols -skip qtquickcontrols2 \ + -skip serialbus -skip webengine \ + -nomake examples -nomake tests -nomake tools && \ + make -j$THREADS && \ + make -j$THREADS install && \ + cd qttools/src/linguist/lrelease && \ + ../../../../qtbase/bin/qmake && \ + make -j$THREADS && \ + make -j$THREADS install && \ + cd ../../../.. && \ + rm -rf $(pwd) + +RUN git clone -b libgpg-error-1.38 --depth 1 git://git.gnupg.org/libgpg-error.git && \ + cd libgpg-error && \ + git reset --hard 71d278824c5fe61865f7927a2ed1aa3115f9e439 && \ + ./autogen.sh && \ + ./configure --disable-shared --enable-static --disable-doc --disable-tests \ + --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + cd .. && \ + rm -rf libgpg-error + +RUN git clone -b libgcrypt-1.8.5 --depth 1 git://git.gnupg.org/libgcrypt.git && \ + cd libgcrypt && \ + git reset --hard 56606331bc2a80536db9fc11ad53695126007298 && \ + ./autogen.sh && \ + ./configure --disable-shared --enable-static --disable-doc \ + --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 \ + --with-gpg-error-prefix=/depends/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + cd .. && \ + rm -rf libgcrypt + +# zlib -> libpng, Tor +RUN git clone -b v1.2.11 --depth 1 https://github.com/madler/zlib && \ + cd zlib && \ + git reset --hard cacf7f1d4e3d44d871b605da3b647f07d718623f && \ + CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-ar ./configure --static --prefix=/usr/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) + +# libpng -> libqrencode +RUN git clone -b libpng16 --depth 1 https://github.com/glennrp/libpng.git && \ + cd libpng && \ + git reset --hard dbe3e0c43e549a1602286144d94b0666549b18e6 && \ + CPPFLAGS="-I/depends/x86_64-w64-mingw32/include" LDFLAGS="-L/depends/x86_64-w64-mingw32/lib" \ + ./configure --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) + +RUN git clone -b v4.0.2 --depth 1 https://github.com/fukuchi/libqrencode.git && \ + cd libqrencode && \ + git reset --hard 59ee597f913fcfda7a010a6e106fbee2595f68e4 && \ + ./autogen.sh && \ + CPPFLAGS="-I/depends/x86_64-w64-mingw32/include" LDFLAGS="-L/depends/x86_64-w64-mingw32/lib" \ + ./configure --disable-shared --enable-static --host=x86_64-w64-mingw32 --prefix=/depends/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) + +RUN wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz && \ + echo "e6a1b1b589654277ee790cce3734f07876ac4ccfaecbee8afa0b649cf529cc04 libiconv-1.16.tar.gz" | sha256sum -c && \ + tar -xzf libiconv-1.16.tar.gz && \ + rm libiconv-1.16.tar.gz && \ + cd libiconv-1.16 && \ + ./configure --enable-static --host=x86_64-w64-mingw32 --prefix=/usr/x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) + +# OpenSSL -> Tor +# TODO: Tor will not cross-compile with 1.1.1i +RUN wget https://www.openssl.org/source/openssl-1.0.2u.tar.gz && \ + echo "ecd0c6ffb493dd06707d38b14bb4d8c2288bb7033735606569d8f90f89669d16 openssl-1.0.2u.tar.gz" | sha256sum -c && \ + tar -xzf openssl-1.0.2u.tar.gz && \ + rm openssl-1.0.2u.tar.gz && \ + cd openssl-1.0.2u && \ + ./Configure mingw64 no-shared no-dso --cross-compile-prefix=x86_64-w64-mingw32- --prefix=/usr/local/openssl && \ + make -j$THREADS && \ + make install_sw && \ + rm -rf $(pwd) + +# libevent -> Tor +RUN wget https://github.com/libevent/libevent/releases/download/release-2.1.11-stable/libevent-2.1.11-stable.tar.gz && \ + echo "a65bac6202ea8c5609fd5c7e480e6d25de467ea1917c08290c521752f147283d libevent-2.1.11-stable.tar.gz" | sha256sum -c && \ + tar -zxvf libevent-2.1.11-stable.tar.gz && \ + cd libevent-2.1.11-stable && \ + ./configure --prefix=/usr/local/libevent \ + --disable-shared \ + --enable-static \ + --with-pic \ + --host=x86_64-w64-mingw32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) + +RUN git clone -b tor-0.4.4.6 --depth 1 https://git.torproject.org/tor.git && \ + cd tor && \ + git reset --hard 2a8b789ea6f308d081f369d78fa7cfdc9d00bf90 && \ + ./autogen.sh && \ + ./configure --host=x86_64-w64-mingw32 \ + --disable-asciidoc \ + --disable-zstd \ + --disable-lzma \ + --disable-manpage \ + --disable-html-manual \ + --disable-system-torrc \ + --disable-module-relay \ + --enable-static-tor \ + --with-libevent-dir=/usr/local/libevent \ + --with-openssl-dir=/usr/local/openssl \ + --with-zlib-dir=/usr/x86_64-w64-mingw32 \ + --disable-tool-name-check \ + --enable-fatal-warnings \ + --prefix=/usr/local/tor \ + LIBS=-lcrypt32 && \ + make -j$THREADS && \ + make -j$THREADS install && \ + rm -rf $(pwd) diff --git a/Dockerfile_windows b/Dockerfile.windows_mxe similarity index 100% rename from Dockerfile_windows rename to Dockerfile.windows_mxe diff --git a/Makefile b/Makefile index fe1a511..7ef1c5e 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,10 @@ release-static: cmake -Bbuild $(CMAKEFLAGS) $(MAKE) -Cbuild +depends: + mkdir -p build/$(target)/release + cd build/$(target)/release && cmake -D STATIC=ON -DTOR_BIN=$(or ${TOR_BIN},OFF) -D DEV_MODE=$(or ${DEV_MODE},OFF) -D BUILD_TAG=$(tag) -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$(root)/$(target)/share/toolchain.cmake ../../.. && $(MAKE) + windows-mxe-release: CMAKEFLAGS += -DBUILD_TAG="win-x64" windows-mxe-release: CMAKEFLAGS += -DTOR_BIN=$(or ${TOR_BIN},OFF) windows-mxe-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release @@ -69,4 +73,4 @@ mac-release: CMAKEFLAGS += -DCMAKE_BUILD_TYPE=Release mac-release: cmake -Bbuild $(CMAKEFLAGS) $(MAKE) -Cbuild - $(MAKE) -Cbuild deploy \ No newline at end of file + $(MAKE) -Cbuild deploy diff --git a/cmake/FindQREncode.cmake b/cmake/FindQREncode.cmake index 2f93c2b..8fe6bbb 100644 --- a/cmake/FindQREncode.cmake +++ b/cmake/FindQREncode.cmake @@ -1,5 +1,8 @@ find_path(QRENCODE_INCLUDE_DIR qrencode.h) +message(STATUS "QRENCODE PATH ${QRENCODE_INCLUDE_DIR}") + find_library(QRENCODE_LIBRARY qrencode) +message(STATUS "QRENCODE LIBARY ${QRENCODE_LIBRARY}") mark_as_advanced(QRENCODE_LIBRARY QRENCODE_INCLUDE_DIR) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 99c870a..d7d297e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -58,7 +58,8 @@ if(MINGW) set(ICON_RC ${CMAKE_CURRENT_BINARY_DIR}/icon.rc) set(ICON_RES ${CMAKE_CURRENT_BINARY_DIR}/icon.o) file(WRITE ${ICON_RC} "IDI_ICON1 ICON DISCARDABLE \"${ICON}\"") - add_custom_command(OUTPUT ${ICON_RES} COMMAND windres ${ICON_RC} ${ICON_RES} MAIN_DEPENDENCY ${ICON_RC}) + find_program(Qt5_WINDRES_EXECUTABLE NAMES windres x86_64-w64-mingw32-windres REQUIRED CMAKE_FIND_ROOT_PATH_BOTH) + add_custom_command(OUTPUT ${ICON_RES} COMMAND ${Qt5_WINDRES_EXECUTABLE} ${ICON_RC} ${ICON_RES} MAIN_DEPENDENCY ${ICON_RC}) list(APPEND RESOURCES ${ICON_RES}) endif() @@ -80,6 +81,7 @@ set_target_properties(feather PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" MACOSX_BUNDLE TRUE MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/utils/Info.plist" + LINK_FLAGS_RELEASE -s ) set_property(TARGET feather PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")