Versions: 3.04 & 3.05
System: Cross-compiling i686-w64-mingw32 from darwin/linux
Error:
i686-w64-mingw32.static-g++ -o build/urelease/stub_bzip2-x86-unicode/stub_bzip2.exe -s -mwindows -nostdlib -Wl,--exclude-libs,msvcrt.a -Wl,--file-alignment,512 -Wl,-Map,build/urelease/stub_bzip2-x86-unicode/stub_bzip2.map -B pei-i386 -T SCons/Config/linker_script -Wl,-e_NSISWinMainNOCRT -Wl,--subsystem,windows build/urelease/stub_bzip2-x86-unicode/bgbg.o build/urelease/stub_bzip2-x86-unicode/components.o build/urelease/stub_bzip2-x86-unicode/exec.o build/urelease/stub_bzip2-x86-unicode/fileform.o build/urelease/stub_bzip2-x86-unicode/Main.o build/urelease/stub_bzip2-x86-unicode/plugin.o build/urelease/stub_bzip2-x86-unicode/Ui.o build/urelease/stub_bzip2-x86-unicode/util.o build/urelease/stub_bzip2-x86-unicode/crc32.o build/urelease/stub_bzip2-x86-unicode/bzlib.o build/urelease/stub_bzip2-x86-unicode/decompress.o build/urelease/stub_bzip2-x86-unicode/huffman.o build/urelease/stub_bzip2-x86-unicode/resource.o -L/usr/local/lib -lkernel32 -luser32 -lgdi32 -lshell32 -ladvapi32 -lcomdlg32 -lcomctl32 -lole32 -luuid build/urelease/stub_bzip2-x86-unicode/decompress.o:decompress.c:(.text+0x445): undefined reference to `memmove' build/urelease/stub_bzip2-x86-unicode/decompress.o:decompress.c:(.text+0x942): undefined reference to `memmove' build/urelease/stub_bzip2-x86-unicode/decompress.o:decompress.c:(.text+0x9a2): undefined reference to `memmove' collect2: error: ld returned 1 exit status scons: *** [build/urelease/stub_bzip2-x86-unicode/stub_bzip2.exe] Error 1 scons: building terminated because of errors. make[1]: *** [build-only-nsis_i686-w64-mingw32.static] Error 2
GCC 10 has made changes to memmove
:
To allow inline expansion of both memcpy and memmove, the existing movmem instruction patterns used for non-overlapping memory copies have been renamed to cpymem. The movmem name is now used for overlapping memory moves, consistent with the library functions memcpy and memmove.
and I can seeSCons/Config/gnu
sets:
defenv['NODEFLIBS_FLAG'] = '-nostdlib -Wl,--exclude-libs,msvcrt.a'
along with some special handling for memcpy
and memset
, but didn't get very far with replicating those.
If we could get inline expansion of memcpy that would be nice but it appears GCC is inserting a call to one of its own internal functions here which is the opposite of what we want.
You could try this in decompress.c:
After the
#include "bzlib.h"
line, addextern void NSISCALL mini_memcpy(void *out, const void *in, UINT_PTR cb);
Two places in the file there is some code that does somthing that looks like
xxx=yyy;//mini_memcpy(&sv, &(s->save), sizeof(sv));
Remove the
xxx=yyy;//
part so you are just left withmini_memcpy(
....This should remove at least two of the undefined reference errors. The last one I can't tell just by looking at the code, you could try commenting stuff out until the error goes away and tell me which line the problem is on.
I'm not using darwin, but I am trying Fedora 32 with gcc 10.
Are you using 'XGCC_WIN32_PREFIX' at all? i686-w64-mingw32.static-g++ is not in the list of recognised compilers for nsis. Regular compiler without the '.static' part compiles fine.
In SCons/Tools/crossmingw.py on line 169, try changing 'g++' to 'gcc' and see if that makes any difference. The stubs should compile but the plugins won't link properly.
Maybe we could switch the stubs so that it only uses gcc to link instead of g++? (I'll have to test that out first).
A bit of research on i686-w64-mingw32.static-g++ shows that it's related to MXE, which I have never heard of before. Technically it should work, but the most likely answer is the environment or compiler is wrong.
Sorry, mxe is a cross-compiler (I'm a maintainer) which builds gcc and various other packages. Most other packages were fairly easy fixes with gcc10, the usual extra warnings and some other porting notes.
The use of
-nostdlib
is a little beyond me ;)Yes, we also do some sed replacements on 64-bit targets, and use a pinned version of scons-local (currently at 3.0.1). The nsis build rule is:
https://github.com/mxe/mxe/blob/master/src/nsis.mk
I'll try the changes earlier in the thread, and also removing the suffix. We've been using the static/shared suffixes since 2014 and it's working fine with gcc5 and gcc9 (probably gcc6|7|8 also, but I haven't tested those).
-nostdlib is used because we don't want the stubs to depend on C runtime libraries for the installers to run, they should be pure windows code only. Hence our own versions of memcpy and memset, and windows specific calls instead of C runtime calls.
Ok, it's good that the .static compiler works fine in older versions. I would suggest leaving the compiler command line the way it is (leave it as g++). I don't have an OS to test this on, so there isn't much I can do to help. Darwin is Apple based, right? I have never touched an Apple device before.
Is
-static-libgcc
a possible way to avoid runtime dependencies?The only downside to static linking the runtime is the size increase on the stubs. You could do that, but we would prefer not to do that (for compatibility reasons on older OS's, like Win 95 and Win XP).
I'll try installing MXE on my Fedora VM, since it has GCC 10 on it already. If I can replicate the error, then I can troubleshoot it more effectively.
Yes, though mxe should work on any unix like system. If you've got cycles
to spare, you can review the requirements at:
https://mxe.cc/#requirements-fedora
you probably already have the basic reqs installed and there are some
that aren't needed for nsis (e.g. gdk-pixbuf2-devel). The sanity check
can be skipped with DONT_CHECK_REQUIREMENTS in
make
invocationI've just checked out the svn with:
from the same dir, run:
I'm testing the next part now:
edit: set nsis_SOURCE_TREE=/path/to/repo correctly for gcc10
Last edit: Tony 2020-06-14
Same original error with gcc10 on
nsis-code/NSIS/trunk
. The full log:will show the various commands, the important line is the one after "# scons does various PATH manipulations", it's along the lines of
cd {source_dir} && {scons} {options} install
(the /usr/local/... tests are for FreeBSD and can be omitted).mxe doesn't "install" itself, none of the compilers/tools are available by default. To reproduce the error in a terminal session, run:
then copy/paste the scons line from above.
Alternately, you can run something like:
I don't know what the SKIPUTILS and NSIS_MAX_STRLEN do, but we're testing gcc9 vs gcc10 - so keep everything else the same.
SKIPUTILS just skips those items to be built. Those 4 in the list are all windows GUI programs, so they can't be run on non-windows anyway. Skipping them just speeds up the build. NSIS_MAX_STRLEN sets the internal string size of the variables in the nsis script, ie $1, $2, etc. Default is 1024, but for our purposes it doesn't matter what it's set to.
Oh, and my poor VM. I have a spare laptop that I can wipe and install fedora on, running it on proper hardware should be quicker. I will see how it goes (this takes much longer than I thought).
Indeed!
Does SourceForge have a way of fetching a user's public ssh key, or do you have a github account?
I can set you up with a temp login on our package building server. It's not the fastest, but it is the quickest way to replicate the issue.
Hi guys.
I've been struggling with this issue myself for a few days...
Indeed, the gcc10 optimizer identifies code that moves memory and replaces it with msvcrt!memmove calls.
My approach was to disable these optimizations in
decompress.c
by using thevolatile
qualifier on destination addresses.For instance, the line decompress.c:266
...would become...
See my full commit here.
My VM ran out of disk space, so I ended up installing Fedora on a spare laptop.
I did manage to replicate the error that Tony ran into, and Marius did actually find the fix for it.
So I compiled the source manually using Tonys instructions, compiled WelcomeFinish.nsi, as well as my own alltest.nsi using bzip2 compression, and ran the installers on my windows machine. Everything appears to run fine, even the uninstallers too.
So that's one confirmed report from me.
edit: I didn't want to download the whole nsis source tree, so I downloaded just the trunk and changed the rest of the paths to it.
Last edit: Jason 2020-06-15
I can also confirm the patch from Marius fixes the gcc10 build, and causes no isssues with gcc5 or gcc9.
Thanks!
edit: That was tested on trunk, the patch also applies to the latest release v3.05. mxe is updated so this can be closed from my perspective.
Last edit: Tony 2020-06-15
Instead of a typecast, could we just rewrite the destination like so?
I've already wiped my fedora install, so I can't test this straight away. I know the nsis devs don't particularly like typecasts, so doing this without a typecast would be better.
I'm afraid this wouldn't work.
From compiler's perspective
*(pos + v)
is the same aspos[v]
. You'll get the same linker error.It's the
volatile
keyword that turns off compiler optimizations and prevents memmove calls.Another approach would be to enclose the entire
decompress.c
into a pragma block like so:That would turn off optimizations on the entire file, and, get rid of typecasts...
I don't have a problem with the cast but volatile uchar needs to be a define so it only gets applied to GCC >= 10 because the Microsoft compiler adds a fence around volatile writes.
I found a reference to version checking here: https://sourceforge.net/p/predef/wiki/VersionNormalization/
So we could do something like:
I have to double-check if mingw also defines GNUC etc.
gcc/mingw pre-defines
mingw windows.h defines
I checked an old mingw32 version from 2007 (4.2.1 on ubuntu 12.04), and it works on that. I also checked mingw-w64 on 18.04 and it shows 7.3.0.
After some more research I think there's a better way to fix this...
It turns out that
-fno-tree-loop-distribute-patterns
flag turns off the pattern recognition (such as memmove, memcpy, memset, etc.) and fixes our linker error. It also requires no changes todecompress.c
.More details here (look for "-ftree-loop-distribute-patterns").
Check out my full commit here.
While I like this, it fails with GCC 4.5.2 so we would have to test for it with FlagsConfigure in gnu.
Good point. I've committed the changes here.