Closed k8wu closed 1 year ago
I actually have an ARM Mac with Parallels installed so I should be able to test this. Would you be able to provide more details on how you built the various dependencies (e.g. what you specified for ./configure for wxWidgets, etc.)?
Sure! Here's how we set up the chroot (I use WSL on Windows, but this can also obviously apply for setting up a virtual instance):
In Windows:
In WSL:
sudo apt update && sudo apt install debootstrap rsync
sudo debootstrap stable /opt/aarch64-w64-mingw32
tar -xJvf llvm-mingw-YYYYMMDD-ucrt-ubuntu-YY.MM-aarch64.tar.xz
rsync -avr . ../aarch64-w64-mingw32/usr/local/cross-tools/aarch64-w64-mingw32/
mount -t proc none /opt/aarch64-w64-mingw32/proc
b. Sysfs: mount -t sysfs none /opt/aarch64-w64-mingw32/sys
chroot /opt/aarch64-w64-mingw32
In the chroot (setup):
apt update && apt install locales cmake make autoconf file python3
dpkg-reconfigure locales
PATH=/usr/local/cross-tools/aarch64-w64-mingw32/bin:$PATH
Here's how we get the prerequisites compiled:
apt purge gcc gcc-10 g++ g++-10
b. Go to https://github.com/Hamlib/Hamlib/releases and download the source code for the latest version (4.4 at the time of this writing), and extract it under /usr/src
c. Modify the configure file as follows:
i. On the line for WINLDFLAGS, remove the string -Wl,--add-stdcall-alias
d. Change into the extracted directory and execute the following command to get everything built and installed: ./configure --host=aarch64-w64-mingw32 --without-cxx-binding && make -j4 install
./configure --host=aarch64-w64-mingw32 && make -j4 install
./configure --host=aarch64-w64-mingw32 && make -j4 install
./configure --host=aarch64-w64-mingw32 && make -j4 install
./configure --host=aarch64-w64-mingw32 --disable-neon && make -j4 install
./configure --host=aarch64-w64-mingw32 && make -j4 install
Here's how we get FreeDV (freedv-gui with LPCNet and codec2) compiled:
git clone https://github.com/drowe67/freedv-gui.git
b. Change into the freedv-gui directory and run the following commands to clone the LPCNet and codec2 repositories: git clone https://github.com/drowe67/LPCNet.git && git clone https://github.com/drowe67/codec2.git
c. Follow these steps to get the in-tree LPCNet and codec2 dependencies built:
i. LPCNet
i. Change into the LPCNet directory and underneath that, create a build_windows directory, then change into it and run this command: cmake -D CMAKE_C_COMPILER=aarch64-w64-mingw32-clang -D CMAKE_SKIP_RPATH=1 -D DISABLE_CPU_OPTIMIZATION=ON -D NEON=ON ..
ii. Edit the src/CMakeFiles/lpcnetfreedv.dir/link.txt file and remove the part where it mentions "soname"
iii. Run make -j4
to get the library built
ii. codec2
i. Change into the codec2 directory and underneath that, create a build_windows directory, then change into it and run this command to get the codebook generator built (which has to be native): cmake .. && make -j4
ii. Run this command to set up the actual cross-compilation build: cmake -D CMAKE_C_COMPILER=aarch64-w64-mingw32-clang -D CMAKE_SKIP_RPATH=1 -D LPCNET_BUILD_DIR=/usr/src/freedv-gui/LPCNet/build_windows ..
iii. Edit the src/CMakeFiles/codec2.dir/link.txt and src/CMakeFiles/codec2.dir/relink.txt files and remove the parts where they mention "soname"
iv. Run this command to remove rpath references:
for file in $(grep -r rpath | cut -d":" -f1); do sed -i -e s^-Wl ,-rpath,/usr/src/freedv-gui/codec2/build_windows/src^^g $file; done
v. Run make -j4
to get the library built
d. Change back up to the freedv-gui directory, create a subdirectory called "build_windows", change into it, and execute the following command twice to set up the build: cmake -D CFLAGS="-I/usr/local/include -lws2_32" -D LDFLAGS="-L/usr/local/lib -lws2_32" -D CMAKE_C_COMPILER=aarch64-w64-mingw32-clang -D CMAKE_CXX_COMPILER=aarch64-w64-mingw32-clang++ -D CMAKE_RC_COMPILER=aarch64-w64-mingw32-windres -D CMAKE_SKIP_RPATH=1 -D UNITTEST=0 -D LPCNET_BUILD_DIR=/usr/src/freedv-gui/LPCNet/build_windows -D CODEC2_BUILD_DIR=/usr/src/freedv-gui/codec2/build_windows -D PORTAUDIO_LIBRARY=/usr/local/lib/libportaudio.dll.a -D PORTAUDIO_LIBRARY_DIR=/usr/local/lib -D LIBSAMPLERATE=/usr/local/lib/libsamplerate.dll.a -D LIBSNDFILE=/usr/local/lib/libsndfile.dll.a -D WXCONFIG=/usr/local/bin/wx-config -D wxWidgets_LIBRARIES=/usr/local/lib ..
e. Edit the src/CMakeFiles/freedv.dir/link.txt file as follows:
i. Before -lm
, put the following: /usr/local/lib/libwx_baseu-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_baseu_net-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_baseu_xml-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_adv-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_aui-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_core-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_gl-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_html-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_media-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_propgrid-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_qa-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_ribbon-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_richtext-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_stc-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_webview-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_xrc-3.1-aarch64-w64-mingw32.dll.a
ii. After -lm
, put -lpthread -lws2_32
f. Run this command to compile the program: make -j4
g. Copy the program to a destination directory accessible in Windows, and also copy the following DLLs (you can use find /usr -name _dllname_
to locate them if you're having trouble)
i. libc++.dll
ii. libcodec2.so.1.0
iii. libhamlib-4.dll
iv. liblpcnetfreedv.so.0.4
v. libportaudio-2.dll
vi. libsamplerate-0.dll
vii. libsndfile-1.dll
viii. libspeexdsp-1.dll
ix. libunwind.dll
x. libwinpthread-1.dll
xi. wxbase317u_gcc_custom.dll
xii. wxbase317u_net_gcc_custom.dll
xiii. wxbase317u_xml_gcc_custom.dll
xiv. wxmsw317u_adv_gcc_custom.dll
xv. wxmsw317u_aui_gcc_custom.dll
xvi. wxmsw317u_core_gcc_custom.dll
xvii. wxmsw317u_gl_gcc_custom.dll
xviii. wxmsw317u_html_gcc_custom.dll
xix. wxmsw317u_media_gcc_custom.dll
xx. wxmsw317u_propgrid_gcc_custom.dll
xxi. wxmsw317u_qa_gcc_custom.dll
xxii. wxmsw317u_ribbon_gcc_custom.dll
xxiii. wxmsw317u_richtext_gcc_custom.dll
xxiv. wxmsw317u_stc_gcc_custom.dll
xxv. wxmsw317u_webview_gcc_custom.dll
xxvi. wxmsw317u_xrc_gcc_custom.dllThere may be some weird issues that arise, but I think I got every step that I took to get this to even compile in its present state on this platform.
I think I was able to generate something that works for 2020/2020B. I used your instructions all the way through the dependencies, then did the following:
mingw32.cmake
inside /usr/src/freedv-gui:set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(triple aarch64-w64-mingw32)
set(CMAKE_C_COMPILER ${triple}-clang)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER ${triple}-clang++)
set(CMAKE_CXX_COMPILER_TARGET ${triple})
cmake -DCMAKE_TOOLCHAIN_FILE=/usr/src/freedv-gui/mingw32.cmake .. && make -j4
. It wasn't necessary to remove rpaths or soname references.cmake -DCMAKE_TOOLCHAIN_FILE=/usr/src/freedv-gui/mingw32.cmake -DLPCNET_BUILD_DIR=/usr/src/freedv-gui/LPCNet/build_windows ..
Again, no need to remove rpaths or soname references.set(USE_STATIC_PORTAUDIO TRUE)
.
b. Modify src/CMakeLists.txt
to remove the reference to usb-1.0.
c. Run cmake -DCMAKE_TOOLCHAIN_FILE=/usr/src/freedv-gui/mingw32.cmake -DLPCNET_BUILD_DIR=/usr/src/freedv-gui/LPCNet/build_windows -DCODEC2_BUILD_DIR=/usr/src/freedv-gui/codec2/build_windows -DPORTAUDIO_LIBRARY=/usr/local/lib/libportaudio.dll.a -DPORTAUDIO_LIBRARY_DIR=/usr/local/lib .. && make -j4
Anyway, I also made the same change to force isAvxEnabled to be true and I seem to be able to decode the sample 2020 .wav file with no problem using these steps. Can you confirm whether this set of instructions works for you too?
Very good! At the least, the build process has been simplified somewhat for the FreeDV-related items.
I followed your instructions and did new builds of the LPCNet, codec2, and freedv-gui projects, then copied the resultant EXE and DLL files to my Windows-accessible location and ran the program. Here is what it shows - 2020 is greyed out, but 2020B is available:
Upon attempting to select the 2020B mode, we get hit with an assertion error, but at least it's caught and handled without killing the program:
I was able to decode the sample WAV files in the LPCNet wav directory using the Windows versions of the command-line tools that were compiled along the way (c2demo.exe, in particular). I'm not sure which ones are 2020 or 2020B.
EDIT: Oops, I missed the bit about the modification in freedv-gui/src/util.cpp. I did that, and now I can select the 2020 and 2020B modes without it bombing out with an assertion failure error. I will try some on-air tests later today.
I followed your instructions and did new builds of the LPCNet, codec2, and freedv-gui projects, then copied the resultant EXE and DLL files to my Windows-accessible location and ran the program. Here is what it shows - 2020 is greyed out, but 2020B is available:
...
Upon attempting to select the 2020B mode, we get hit with an assertion error, but at least it's caught and handled without killing the program:
Yeah, that's definitely a bug. I opened https://github.com/drowe67/freedv-gui/pull/279 to resolve that particular issue. 👍
I was able to decode the sample WAV files in the LPCNet wav directory using the Windows versions of the command-line tools that were compiled along the way (c2demo.exe, in particular). I'm not sure which ones are 2020 or 2020B.
I was testing by going to Tools->Start Play File - From Radio and selecting the files from https://github.com/drowe67/freedv-gui/tree/master/wav. CPU usage in the Parallels VM seemed to top out at 15-20% or so, FWIW.
Anyway, it may be worthwhile to figure out some alternative way to determine whether a particular non-x86 system can support 2020/2020B. That may need some thought, though.
After I did the modification to src/util.cpp to allow the total whitelisting of the aarch64 architecture regardless of platform, 2020 and 2020B modes are now working within freedv-gui on both transmit and receive. When transmitting, the process takes around 5% to 7% of the total CPU, peaking occasionally to 10%. Playing the all.wav file results in the same amount of CPU being used (5% or so). It may take a bit more on an SQ1 processor, or even a different one such as the version of the Qualcomm Snapdragon that Lenovo uses in their new ARM laptop, but generally speaking, it should be fine regardless of OS.
After I did the modification to src/util.cpp to allow the total whitelisting of the aarch64 architecture regardless of platform, 2020 and 2020B modes are now working within freedv-gui on both transmit and receive. When transmitting, the process takes around 5% to 7% of the total CPU, peaking occasionally to 10%. Playing the all.wav file results in the same amount of CPU being used (5% or so). It may take a bit more on an SQ1 processor, or even a different one such as the version of the Qualcomm Snapdragon that Lenovo uses in their new ARM laptop, but generally speaking, it should be fine regardless of OS.
For those devices with enough CPU power, yep. However, there are definitely those that can't decode 2020 or 2020B in real time (for example, Raspberry Pi 4), so those modes should probably still be blocked on those platforms.
One thought I had is to do a benchmark the first time someone starts FreeDV using the sample 2020 .wav file. If that file can be decoded in Y% of real time (where Y is some sort of value >= 100% that we figure out), 2020 and 2020B get enabled. Otherwise, they're disabled. Personally I'd probably set Y to be at least 200% of real time to take into account other stuff running on a user's machine but I'm open to suggestions.
That's probably the best way to go about it - that way, regardless of OS or CPU architecture, the program would know for sure whether it could reliably process 2020 modes in real time with enough system resources to spare for other tasks. Let's say we have 2 seconds of 2020 mode data. If the decode operation takes 1 second or less, then 2020 and 2020B could be enabled without any further issue. If the decode operation takes between 1 and 1.75 seconds, then they could still be enabled, but a warning could be shown to the user indicating that there may be performance degradation depending on what else the system is doing while FreeDV is running. Anything more than 1.75 seconds would result in 2020/2020B being disabled, since it's almost a given at that point that the system doesn't have the necessary resources for those modes.
At that point, I don't think that CPU architecture or operating system/platform would have anything to do with it - it's all down to how fast the system can process the data.
Side note: I was thinking, with this way of compiling a Windows ARM64 version of FreeDV and its dependencies, that this process could also technically be used to compile x86 and x64 versions, since the LLVM toolchain has the ability to target i686-w64-mingw32 and x86_64-w64-mingw32 in addition to aarch64-w64-mingw32. It would probably take more CMakeLists.txt edits to make it work without breaking non-Windows builds, but it could probably be done.
Yeah, I was actually about to try to build an ARM Windows build before you created this bug :) It might be a good idea longer term to use LLVM for Windows builds, assuming that packages eventually end up in a form that's easily included in the current Docker container.
Anyway, can you give https://github.com/drowe67/freedv-gui/pull/280 a shot? It's a first pass at an alternate way of determining whether 2020 mode will work on non-x86 machines.
I have merged this on my x86 system just for completeness, when I run it the debug output is:
Making sure your machine can handle 2020 mode: Generating test audio... Decoding modulated audio... One second of 2020 decoded in 143 ms 2020 allowed: 1
so it appears that the code works correctly. I have all the 2020x modes compiled in and enabled with the latest locally built and installed codec2 and lpcnetfreedv libraries.
Yeah, I was actually about to try to build an ARM Windows build before you created this bug :) It might be a good idea longer term to use LLVM for Windows builds, assuming that packages eventually end up in a form that's easily included in the current Docker container.
Anyway, can you give #280 a shot? It's a first pass at an alternate way of determining whether 2020 mode will work on non-x86 machines.
@tmiw I followed the directions in https://github.com/drowe67/freedv-gui/issues/278#issuecomment-1246583237 after checking out the "ms-2020-detection" branch, and it resulted in a working freedv.exe executable. I ran it with a new config so it would do the 2020 test, and it said that it was allowing the 2020 modes because it decoded 1 second of 2020 in 368 ms. Therefore, this branch, with the previous modifications from the earlier comment in this thread, results in success on Windows 11 on ARM64.
Yeah, I was actually about to try to build an ARM Windows build before you created this bug :) It might be a good idea longer term to use LLVM for Windows builds, assuming that packages eventually end up in a form that's easily included in the current Docker container. Anyway, can you give #280 a shot? It's a first pass at an alternate way of determining whether 2020 mode will work on non-x86 machines.
@tmiw I followed the directions in #278 (comment) after checking out the "ms-2020-detection" branch, and it resulted in a working freedv.exe executable. I ran it with a new config so it would do the 2020 test, and it said that it was allowing the 2020 modes because it decoded 1 second of 2020 in 368 ms. Therefore, this branch, with the previous modifications from the earlier comment in this thread, results in success on Windows 11 on ARM64.
I just tested on my M1 Mac, too:
I'm going to also try on my Raspberry Pi 4 at some point this weekend to make sure 2020 mode is still blocked there.
Found a bug testing on the Raspberry Pi but after fixing:
Making sure your machine can handle 2020 mode:
Generating test audio...
Decoding modulated audio...
One second of 2020 decoded in 1124 ms
2020 allowed: 0
FYI - just tested the compilation with the latest (v1.8.5-20221030) version using the process outlined in this earlier comment - with the exception that you no longer have to remove the "usb-1.0" reference from the src/CMakeLists.txt file, and it looks like the "aarch64" check in src/util.cpp is now no longer necessary (which we discussed earlier in this thread). I am able to build for Windows on ARM64 still, and it allows me to use the 2020* modes.
I suppose I should try this with Ninja instead of Make, because that's one more step toward being able to use native Windows build tools for at least the parts of this process that can use CMake instead of configure scripts.
Update: I've been doing some build system enhancements to make this easier (#305). I've gotten to the point where I can execute the following with that PR branch and it builds almost everything:
export FREEDV_DIR=`pwd`
git clone https://github.com/drowe67/LPCNet.git
cd LPCNet
mkdir build_windows
cmake -DCMAKE_TOOLCHAIN_FILE=$FREEDV_DIR/freedv-llvm-aarch64.cmake ..
make
cd $FREEDV_DIR
git clone https://github.com/drowe67/codec2.git
cd codec2
mkdir build_windows
cmake -DCMAKE_TOOLCHAIN_FILE=$FREEDV_DIR/freedv-llvm-aarch64.cmake -DLPCNET_BUILD_DIR=$FREEDV_DIR/LPCNet/build_windows ..
make
cd $FREEDV_DIR
mkdir build_windows
cd build_windows
export PATH=/Users/mooneer/Downloads/llvm-mingw-20220906-ucrt-macos-universal/bin:$PATH
cmake -DCMAKE_TOOLCHAIN_FILE=$FREEDV_DIR/freedv-llvm-aarch64.cmake -DLPCNET_BUILD_DIR=$FREEDV_DIR/LPCNet/build_windows -DCODEC2_BUILD_DIR=$FREEDV_DIR/codec2/build_windows -DBOOTSTRAP_WXWIDGETS=1 ..
make
Unfortunately it fails during linking with the following:
[100%] Linking CXX executable freedv.exe
lld: error: unable to find library -lws2_32.lib
lld: error: unable to find library -lusb-1.0.lib
lld: error: unable to find library -ldsound.lib
lld: error: unable to find library -lsetupapi.lib
lld: error: unable to find library -lwinhttp.lib
lld: error: unable to find library -lkernel32.lib
lld: error: unable to find library -luser32.lib
lld: error: unable to find library -lgdi32.lib
lld: error: unable to find library -lcomdlg32.lib
lld: error: unable to find library -lwinspool.lib
lld: error: unable to find library -lwinmm.lib
lld: error: unable to find library -lshell32.lib
lld: error: unable to find library -lshlwapi.lib
lld: error: unable to find library -lcomctl32.lib
lld: error: unable to find library -lole32.lib
lld: error: unable to find library -loleaut32.lib
lld: error: unable to find library -luuid.lib
lld: error: unable to find library -lrpcrt4.lib
lld: error: unable to find library -ladvapi32.lib
lld: error: unable to find library -lversion.lib
lld: error: too many errors emitted, stopping now
I think it's something with the toolchain file I'm using but it's not that much different from the one I suggested. (.a files exist for the above, but not .lib.) Any ideas would be appreciated.
You don't need to add the ".lib" extension. If you find a way to get rid of those on the ld command line, it should find those libraries as long as the compiler's bin directory is in your path (for example, on Linux, mine is currently /usr/local/cross-tools/llvm-mingw-20220323-ucrt-ubuntu-18.04-aarch64/bin (though you might be using a different build - there's a 20220906 one now).
You don't need to add the ".lib" extension. If you find a way to get rid of those on the ld command line, it should find those libraries as long as the compiler's bin directory is in your path (for example, on Linux, mine is currently /usr/local/cross-tools/llvm-mingw-20220323-ucrt-ubuntu-18.04-aarch64/bin (though you might be using a different build - there's a 20220906 one now).
Interestingly, I'm not explicitly adding the .lib extension; something in the CMake process is doing so.
As for setup, the bin folder is indeed in my path but I see the following:
Mooneers-16-MacBook-Pro-2325:build_osx mooneer$ ls ~/Downloads/llvm-mingw-20220906-ucrt-macos-universal/aarch64-w64-mingw32/lib/lib*
/Users/mooneer/Downloads/llvm-mingw-20220906-ucrt-macos-universal/aarch64-w64-mingw32/lib/libacledit.a
/Users/mooneer/Downloads/llvm-mingw-20220906-ucrt-macos-universal/aarch64-w64-mingw32/lib/libactiveds.a
/Users/mooneer/Downloads/llvm-mingw-20220906-ucrt-macos-universal/aarch64-w64-mingw32/lib/libadsiid.a
...
Mooneers-16-MacBook-Pro-2325:build_osx mooneer$
I also tried setting CMAKE_SYSTEM_NAME
to Windows-Clang
and Windows-LLVM
(since CMake seems to look for a file named Platform/${CMAKE_SYSTEM_NAME}.cmake
to load settings from) and both of those gave me different errors. Specifically, the wxWidgets configuration seemed unable to figure out that I was building for Windows and errored out. I'm wondering if I need to specify "Clang" or "LLVM" in another variable instead?
Good news--it looks like it was an issue with the CMake version in MacPorts. "Windows" inside the toolchain file seems to work fine on 3.25 (the version in Ubuntu 22.04). Still need to investigate why I can't produce installer packages, though.
So yeah, if you have CMake 3.25 or greater, you can do the following to get an installer that's usable on ARM (tested on Ubuntu 22.04):
$ git clone https://github.com/drowe67/freedv-gui.git
$ cd freedv-gui
$ git checkout ms-simple-build
$ mkdir build_windows
$ cd build_windows
$ export PATH=/path/to/llvm-mingw-20220906-ucrt-ubuntu-18.04-x86_64/bin:$PATH
$ cmake -DBOOTSTRAP_WXWIDGETS=1 -DCMAKE_TOOLCHAIN_FILE=/path/to/freedv-gui/cross-compile/freedv-mingw-llvm-aarch64.cmake ..
$ make
$ make package
(note: this downloads and compiles all dependencies, so this may take a while)
Feel free to give it a try and let me know how that goes. It looks like freedv.exe is able to start and decode 2020 using the Windows 11 VM on my M1 Mac Mini, but I'm not sure how well it'll run on other devices.
It almost made it through. I did have to update my CMake to 3.25 (which is in Debian's bullseye-backports repos, so I upgraded it using "apt install -t bullseye-backports cmake"), but it got as far as linking freedv.exe before failing with this error:
[ 98%] Linking CXX executable freedv.exe ld.lld: error: unknown file type: rig.o ld.lld: error: unknown file type: misc.o ld.lld: error: unknown file type: register.o ld.lld: error: unknown file type: conf.o ld.lld: error: unknown file type: debug.o clang-15: error: linker command failed with exit code 1 (use -v to see invocation) make[2]: *** [src/CMakeFiles/freedv.dir/build.make:488: src/freedv.exe] Error 1 make[1]: *** [CMakeFiles/Makefile2:2717: src/CMakeFiles/freedv.dir/all] Error 2 make: *** [Makefile:156: all] Error 2
I am using the latest LLVM toolchain from /mstorsjo/llvm-mingw, and I am building on my usual Debian Bullseye (11) system under WSL2:
$ uname -a Linux K8WU-SPX 5.15.74.2-microsoft-standard-WSL2 #1 SMP Wed Nov 2 19:50:29 UTC 2022 aarch64 GNU/Linux
Is it possible that maybe it's using the wrong lld for some reason? Try running make VERBOSE=1
and pasting what command it's using exactly for the link step?
Here's the relevant part of the output after running make VERBOSE=1
:
[ 98%] Linking CXX executable freedv.exe
cd /home/mphipps/src-local/freedv-gui/build_windows/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/freedv.dir/link.txt --verbose=1
/usr/bin/cmake -E rm -f CMakeFiles/freedv.dir/objects.a
/usr/local/cross-tools/llvm-mingw-20220906-ucrt-ubuntu-18.04-aarch64/bin/llvm-ar qc CMakeFiles/freedv.dir/objects.a @CMakeFiles/freedv.dir/objects1
/usr/local/cross-tools/llvm-mingw-20220906-ucrt-ubuntu-18.04-aarch64/bin/aarch64-w64-mingw32-clang++ --target=aarch64-w64-mingw32 -Wall -g -mwindows -Wl,--whole-archive CMakeFiles/freedv.dir/objects.a -Wl,--no-whole-archive -o freedv.exe -Wl,--out-implib,libfreedv.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/freedv.dir/linkLibs.rsp
ld.lld: error: unknown file type: rig.o
ld.lld: error: unknown file type: misc.o
ld.lld: error: unknown file type: register.o
ld.lld: error: unknown file type: conf.o
ld.lld: error: unknown file type: debug.o
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [src/CMakeFiles/freedv.dir/build.make:488: src/freedv.exe] Error 1
make[2]: Leaving directory '/home/mphipps/src-local/freedv-gui/build_windows'
make[1]: *** [CMakeFiles/Makefile2:2717: src/CMakeFiles/freedv.dir/all] Error 2
make[1]: Leaving directory '/home/mphipps/src-local/freedv-gui/build_windows'
make: *** [Makefile:156: all] Error 2
Addendum: It seems to me like it should be calling aarch64-w64-mingw32-ar
instead of llvm-ar
.
Addendum: It seems to me like it should be calling
aarch64-w64-mingw32-ar
instead ofllvm-ar
.
I pushed a commit that should hopefully help with that. Try again?
It still bombs when it comes time to link freedv.exe:
[ 98%] Linking CXX executable freedv.exe
cd /home/mphipps/src-local/freedv-gui/build_windows/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/freedv.dir/link.txt --verbose=1
/usr/bin/cmake -E rm -f CMakeFiles/freedv.dir/objects.a
aarch64-w64-mingw32-ar qc CMakeFiles/freedv.dir/objects.a @CMakeFiles/freedv.dir/objects1
/usr/local/cross-tools/llvm-mingw-20220906-ucrt-ubuntu-18.04-aarch64/bin/aarch64-w64-mingw32-clang++ --target=aarch64-w64-mingw32 -Wall -g -mwindows -Wl,--whole-archive CMakeFiles/freedv.dir/objects.a -Wl,--no-whole-archive -o freedv.exe -Wl,--out-implib,libfreedv.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles/freedv.dir/linkLibs.rsp
ld.lld: error: unknown file type: rig.o
ld.lld: error: unknown file type: misc.o
ld.lld: error: unknown file type: register.o
ld.lld: error: unknown file type: conf.o
ld.lld: error: unknown file type: debug.o
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [src/CMakeFiles/freedv.dir/build.make:488: src/freedv.exe] Error 1
make[2]: Leaving directory '/home/mphipps/src-local/freedv-gui/build_windows'
make[1]: *** [CMakeFiles/Makefile2:2717: src/CMakeFiles/freedv.dir/all] Error 2
make[1]: Leaving directory '/home/mphipps/src-local/freedv-gui/build_windows'
make: *** [Makefile:156: all] Error 2
Given that it's saying that the file type of these object files isn't recognized, I would say that something didn't get built correctly earlier in the process. Looking through the output, nothing jumps out at me, though.
After merging the latest master into that branch, I started having linker errors as well (though not exactly the same errors you got). Turns out that I needed to add -fstack-protector
to CMAKE_C_FLAGS
whenever hamlib was being statically built. Considering that the files in the error you got are also hamlib related, I wonder if that will fix your errors too. Might be worth pulling down the latest to try again regardless.
I'm off at my day job for the rest of the year, so I'm going through PRs and issues still in progress. It looks like the x86_64 installer generated using PR #305 works properly here. Once I've gone through and made sure the existing build scripts still work properly I'll merge the PR.
(The LLVM MinGW instructions have also been added to the README as experimental. Eventually we can transition over to using those for official binaries once there's more runtime.)
All good. Thanks for your help, @k8wu!
Hello,
I have a Microsoft Surface Pro X tablet with an SQ2 (ARMv8) CPU, and it runs Windows 11 Pro. Of course, this configuration is an outlier in terms of what most hams (or even most people in general) would use for a Windows machine, but it's what I bought to replace a very old Dell Latitude laptop that I used to use for Amateur Radio purposes. I've been slowly working through the open source projects that I use to get native ARM64 versions built. So far, I've been successful with Fldigi and DOSBox (which I use for an old Yagi modeling program), but of course, the more complicated the software is, the harder it is to compile for this platform.
Because there does not exist a GCC-based toolchain to target aarch64-w64-mingw32, I am instead using the LLVM-based one that is developed here. I have a Debian Bullseye installation running via WSL2, and I use a separate chroot with that installation for each project that I want to build. The aarch64-w64-mingw32 toolchain is available in each one.
I am able to manually build a somewhat-working FreeDV executable for Windows on ARM64. I build the pre-requisites (Hamlib, SpeexDSP, wxWidgets 3.1, libsndfile, libsamplerate, and PortAudio), and install them into /usr/local in the chroot, since I don't care about /usr/local getting junked up with cross-compiled libraries because I won't be running any compiled software within it. I then check out freedv-gui, then go into that directory and check out LPCNet and codec2. LPCNet is then built with automatic optimizations disabled and NEON manually enabled (which as I understand it would happen anyway because NEON optimizations are required for AArch64). A "native" build of codec2 is then performed just to get the
generate_codebook
executable to be available to the cross-compilation process the second time through, and LPCNet is referenced on that cross-compilation build.At this point, we can then build freedv-gui by running this twice (for some reason, the cmake process fails the first time around):
cmake -D CFLAGS="-I/usr/local/include -lws2_32" -D LDFLAGS="-L/usr/local/lib -lws2_32" -D CMAKE_C_COMPILER=aarch64-w64-mingw32-clang -D CMAKE_CXX_COMPILER=aarch64-w64-mingw32-clang++ -D CMAKE_RC_COMPILER=aarch64-w64-mingw32-windres -D CMAKE_SKIP_RPATH=1 -D UNITTEST=0 -D LPCNET_BUILD_DIR=/usr/src/freedv-gui/LPCNet/build_windows -D CODEC2_BUILD_DIR=/usr/src/freedv-gui/codec2/build_windows -D PORTAUDIO_LIBRARY=/usr/local/lib/libportaudio.dll.a -D PORTAUDIO_LIBRARY_DIR=/usr/local/lib -D LIBSAMPLERATE=/usr/local/lib/libsamplerate.dll.a -D LIBSNDFILE=/usr/local/lib/libsndfile.dll.a -D WXCONFIG=/usr/local/bin/wx-config -D wxWidgets_LIBRARIES=/usr/local/lib ..
We have to manually edit the src/CMakeFiles/freedv.dir/link.txt file as follows: i. Before "-lm", put the following:
/usr/local/lib/libwx_baseu-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_baseu_net-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_baseu_xml-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_adv-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_aui-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_core-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_gl-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_html-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_media-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_propgrid-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_qa-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_ribbon-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_richtext-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_stc-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_webview-3.1-aarch64-w64-mingw32.dll.a /usr/local/lib/libwx_mswu_xrc-3.1-aarch64-w64-mingw32.dll.a
ii. After "-lm", put-lpthread -lws2_32
We can then run make to build the program, and then copy the resulting .exe file and its dependent .dll files to a Windows-accessible directory to run.
All this is to say that things work as long as you don't need the 2020 or 2020B modes, but of course, those are why I am interested in FreeDV in the first place, so not having them is a definite deal-breaker. As I understand it by looking at the code, even if LPCNet is compiled with any kind of optimizations in place, freedv-gui uses the
checkAvxSupport()
function to determine whether to enable the 2020 modes, and it looks like running on Windows will always result in that function returning false. I made a local modification to causecheckAvxSupport()
to return true if the platform was "aarch64" regardless of OS (i.e. removing the bit about checking for the macOS platform), and while it does enable those modes, attempting to use them results in a program crash, and I have not yet determined where it's failing since it doesn't echo anything to standard output when it happens.The question then becomes: Is there a better way to enable these modes on Windows on ARM64?