Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows build fixes on a Windows host #1777

Merged
merged 13 commits into from
Jan 20, 2025

Conversation

Doy-lee
Copy link
Collaborator

@Doy-lee Doy-lee commented Jan 13, 2025

Each of the changes are documented in each commit as to reasons why. This still does not fix a Windows build on a Windows host for reasons that are still beyond me at this point, but it gets all the way to the linking step instead of crashing and burning much earlier.

On a Windows host, the build fails when trying to create the final executables with the following error excerpts:

[ 96%] Linking CXX executable ../../bin/oxen-wallet-rpc.exe

cd /C/ox/build/release/src/wallet && /C/msys/mingw64/bin/cmake.exe -E rm -f CMakeFiles/wallet_rpc_server.dir/objects.a
cd /C/ox/build/release/src/wallet && ar qc CMakeFiles/wallet_rpc_server.dir/objects.a "CMakeFiles/wallet_rpc_server.dir/wallet_rpc_server.cpp.obj" "CMakeFiles/wallet_rpc_server.dir/wallet_rpc_server_commands_defs.cpp.obj"
cd /C/ox/build/release/src/wallet &&
/C/msys/mingw64/bin/x86_64-w64-mingw32-g++.exe  -march=x86-64 -D_GNU_SOURCE
-DWIN32_LEAN_AND_MEAN -Wall -Wextra -Wpointer-arith -Wvla -Wwrite-strings
-Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter
-Wno-unused-variable -Wno-error=unused-variable -Wno-error=uninitialized
-Wlogical-op -Wno-error=maybe-uninitialized -Wno-error=cpp -Wno-error=logical-op
-Wno-error=unused-value -Wno-error=unused-but-set-variable -Wno-reorder
-Wno-missing-field-initializers -Wno-stringop-overflow   -U_FORTIFY_SOURCE
-D_FORTIFY_SOURCE=1 -Wformat -Wformat-security -fstack-protector
-fstack-protector-strong -fcf-protection=full -ftemplate-depth=900 -O3 -DNDEBUG
-Wl,--stack,10485760  -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va
-static  -Wl,--whole-archive CMakeFiles/wallet_rpc_server.dir/objects.a
-Wl,--no-whole-archive -o ../../bin/oxen-wallet-rpc.exe
-Wl,--out-implib,liboxen-wallet-rpc.dll.a
-Wl,--major-image-version,0,--minor-image-version,0
../rpc/common/librpc_common.a libwallet.a ../daemonizer/libdaemonizer.a
../logging/liblogging.a ../../static-deps/lib/libboost_serialization.a
../../static-deps/lib/libboost_program_options.a ../rpc/librpc_commands.a
../rpc/common/librpc_common.a ../../external/libuSockets.a
../../external/libuv/libuv_a.a -lpsapi -luser32 -ladvapi32 -luserenv
../cryptonote_protocol/libcryptonote_protocol.a ../p2p/libp2p.a
../cryptonote_core/libcryptonote_core.a ../multisig/libmultisig.a
../blockchain_db/libblockchain_db.a ../ringct/libringct.a
../sqlitedb/libsqlitedb.a ../checkpoints/libcheckpoints.a
../bls/libbls_aggregator.a ../l2_tracker/libl2_tracker.a
../cryptonote_basic/libcryptonote_basic.a ../device/libdevice.a ../libversion.a
../ringct/libringct_basic.a ../../static-deps/lib/libhidapi.a
../../static-deps/lib/libusb-1.0.a ../bls/libbls_crypto.a
../../external/bn256/src/libbn256.a ../../lib/Release/libethyl.a
../../static-deps/lib/libgmp.a ../../static-deps/lib/libtasn1.a
../../external/SQLiteCpp/libSQLiteCpp.a ../../static-deps/lib/libsqlite3.a
../blocks/libblocks.a ../mnemonics/libmnemonics.a ../net/libnet.a
../../external/db_drivers/liblmdb/liblmdb.a ../rpc/librpc_http_client.a
../../external/ethyl/external/cpr/cpr/libcpr.a ../../static-deps/lib/libcurl.a
../../static-deps/lib/libz.a ../../static-deps/lib/libidn2.a
../../static-deps/lib/libunistring.a ../../static-deps/lib/libiconv.a
../common/libcommon.a ../../static-deps/lib/libboost_serialization.a
../../static-deps/lib/libboost_program_options.a ../crypto/libcncrypto.a
../logging/liblogging.a ../../contrib/epee/src/libepee.a -lmswsock -lws2_32
-liphlpapi -lcrypt32 -lbcrypt -lsetupapi ../../external/oxen-mq/liboxenmq.a
../../static-deps/lib/libzmq.a ../../static-deps/lib/libboost_thread.a
../../external/oxen-logging/liboxen-logging.a
../../external/oxen-logging/spdlog/libspdlog.a
../../external/oxen-logging/fmt/libfmt.a ../../external/randomx/librandomx.a
../../static-deps/lib/libsodium.a -lkernel32 -luser32 -lgdi32 -lwinspool
-lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x28f9): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2901): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2949): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2951): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2999): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x29a1): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x29e9): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x29f1): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2a39): undefined reference to `boost::serialization::extended_type_info::key_unregister() const'
C:/msys/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: CMakeFiles/wallet_rpc_server.dir/objects.a(wallet_rpc_server.cpp.obj):wallet_rpc_server.cpp:(.text+0x2a41): undefined reference to `boost::serialization::typeid_system::extended_type_info_typeid_0::type_unregister()'

The missing symbols are being linked in the linking invocation i.e: ../../static-deps/lib/libboost_serialization.a and a nm dump of the object reveals the exact symbols that the linker is looking for in for example, the text section of the static library. I've pulled down the command that the CI machine cross compiles with and executed the exact same command with failures.

My assessment of the build situation is some platform specific issue regarding binutils is breaking on a Windows machine but doesn't on a Linux machine that is cross-compiling a Windows binary (for example the long file name paths as a platform difference is suspect).

I've tried shuffling linking library order around as ld is sensitive to the order that it's listed on the command line to no success. Potentially something also to do with ld on Windows struggling with a lot of linking libraries. I've had one instance where a build actually succeeded and produced a usable oxend.exe but I was unable to reproduce this. In that build there were no changes to the build script it just intermittently worked somehow.

Unfortunately I don't have a clue what that is for the time being so I'm shipping all the other fixes I've had to make and leave this in a close-to-working but still broken state.

The build had to be updated to using StaticBuild.cmake because MSYS's package manager now ships Boost 1.87 which is incompatible with the codebase (because of legacy epee networking utils that use a deprecated class io_service vs io_context). Since MSYS is constantly updating and deprecating packages and they do not provide a reliable way to access older versioned packages, having a constantly moving target will make the Windows build difficult to maintain, so I've locked it down by forcing a static build.

@jagerman
Copy link
Member

Ignoring that it isn't quite working still, the changes here so far look good to me.

The boost 1.87 transition sounds like it's going to be painful. It might be easier to port the p2p layer to QUIC instead, but I guess we can wait and see how the Monero port ends up. (On the linux side, I don't think boost 1.87+ is likely to land in the next Debian stable release and will probably be a few Ubuntu non-LTS releases until it comes in).

@Doy-lee Doy-lee force-pushed the doyle-windows-build-fix branch from 1e49913 to 9bce032 Compare January 17, 2025 04:44
Doy-lee and others added 9 commits January 17, 2025 16:17
As per docs:

```
  --layout=<layout>       Determine whether to choose library names and header
                          locations such that multiple versions of Boost or
                          multiple compilers can be used on the same system.

                              -- versioned -- Names of boost binaries include
                              the Boost version number, name and version of
                              the compiler and encoded build properties. Boost
                              headers are installed in a subdirectory of
                              <HDRDIR> whose name contains the Boost version
                              number.

                              -- system -- Binaries names do not include the
                              Boost version number or the name and version
                              number of the compiler. Boost headers are
                              installed directly into <HDRDIR>. This option is
                              intended for system integrators building
                              distribution packages.

                          The default value is 'versioned' on Windows, and
                          'system' on Unix.
```

A Windows build with a Windows host defaults to 'versioned' which dumps
files into the sysroot currently as 'include/boost-1_86/boost/...' which breaks
the build as our CPP files look for '<boost/...>'.
This was previously only set on cross-compiling builds but it also needs to be
set on builds where the host machines is running Windows and using MinGW.
Without this no threading library will be generated by the Boost build.
`cmake -E env` fails to execute the `./configure` command proceeding it
on MSYS MinGW64. It attempts to execute:

```
cd /C/ox/build/release/static-deps-sources/src/zlib_external && /C/Home/Downloads/msys64/mingw64/bin/cmake.exe -E env CC=C:/Home/Downloads/msys64/mingw64/bin/x86_64-w64-mingw32-gcc.exe "CFLAGS=-O2  -fPIC" ./configure --prefix=C:/ox/build/release/static-deps --static
```

And immediately fails with:

```
inappropriate file type or format
```

Something about the way CMake is forwarding args onwards causes a part
one part of the step to fail. You can work around this by chaining `env`
on again with no side-effects and then follow it up with the ./configure
command.
MSYS now packages boost 1.87 which we don't support due to our
dependence on epee and their usage of 'asio::io_service' which was
deprecated in 1.87.

To allow 1.87 we would need to port in changes from Monero, i.e. see
monero-project#9628 which may or may not
be considered at some point but certainly not now.
For some reason MacOS targets are failing with the following error

```
In file included from /tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/src/bls/bls_aggregator.cpp:1:
In file included from /tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/src/bls/bls_aggregator.h:3:
In file included from /tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/src/common/formattable.h:3:
In file included from /tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/external/oxen-logging/fmt/include/fmt/core.h:16:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/memory:884:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocate_at_least.h:13:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/allocator_traits.h:304:9: error: no matching function for call to 'construct_at'
        _VSTD::construct_at(__p, _VSTD::forward<_Args>(__args)...);
        ^~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__config:897:17: note: expanded from macro '_VSTD'
                ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:919:21: note: in instantiation of function template specialization 'std::allocator_traits<std::allocator<eth::(anonymous namespace)::agg_log>>::construct<eth::(anonymous namespace)::agg_log, const service_nodes::service_node_address &, std::string, void, void>' requested here
    __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_),
                    ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:1678:9: note: in instantiation of function template specialization 'std::vector<eth::(anonymous namespace)::agg_log>::__construct_one_at_end<const service_nodes::service_node_address &, std::string>' requested here
        __construct_one_at_end(std::forward<_Args>(__args)...);
        ^
/tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/src/bls/bls_aggregator.cpp:725:39: note: in instantiation of function template specialization 'std::vector<eth::(anonymous namespace)::agg_log>::emplace_back<const service_nodes::service_node_address &, std::string>' requested here
                agg_log_lister->error.emplace_back(
                                      ^
/tmp/drone-WJ2bupWq1Tdvg7M8/drone/src/src/bls/bls_aggregator.cpp:887:41: note: in instantiation of function template specialization 'eth::(anonymous namespace)::aggregate_result<eth::bls_rewards_response>::error<fmt::join_view<std::__wrap_iter<std::string *>, std::__wrap_iter<std::string *>>>' requested here
                    return result_data->error(
                                        ^
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/__memory/construct_at.h:39:38: note: candidate template ignored: substitution failure [with _Tp = eth::(anonymous namespace)::agg_log, _Args = <const service_nodes::service_node_address &, std::string>]: no matching constructor for initialization of 'eth::(anonymous namespace)::agg_log'
_LIBCPP_HIDE_FROM_ABI constexpr _Tp* construct_at(_Tp* __location, _Args&&... __args) {
```

I can't make much sense from this, somehow it doesn't want to forward the
arguments onto the implicit constructor for agg_log so I've pulled it out into
individual assignment statements.
@Doy-lee Doy-lee force-pushed the doyle-windows-build-fix branch from 9bce032 to 7d9de1e Compare January 17, 2025 05:17
It errors with

```
/tmp/drone-ikXKouzy6eNTFeeK/drone/src/src/cryptonote_core/service_node_list.cpp:3381:28: note: 'unconf' declared here
            auto& [txhash, unconf] = *unconf_it;
                           ^
/tmp/drone-ikXKouzy6eNTFeeK/drone/src/src/cryptonote_core/service_node_list.cpp:3429:51: error: reference to local binding 'unconf' declared in enclosing function 'service_nodes::service_node_list::state_t::update_from_block'
                                        .height = unconf.height_added,
```

So just do the simple thing and manually bind them into references.
Static means the function is not exported into the symbol table. Putting
it into the header undoes this by declaring the thing globally across
all TUs. Additionally this then raises a warning that the function is unused.

This is not needed, drop the prototype from the header and reorder the
CPP file to declare it before it's used in the TU.
@Doy-lee Doy-lee enabled auto-merge (rebase) January 20, 2025 05:12
@Doy-lee Doy-lee disabled auto-merge January 20, 2025 05:33
@Doy-lee Doy-lee merged commit f51d43a into oxen-io:dev Jan 20, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants