-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Multiple definitions of symbol PC when statically linking readline and termcap into a program #8105
Comments
Can you provide a simple code to reproduce your issue? |
does it pr chance also link to one of the curses libraries ? PC is defined in them as well. |
The code I'm building does not appear to link to curses. The code I'm building is the jzintv emulator. I have access to a slightly more recent version, but this aspect has not changed and the code here will likely reproduce the issue as well. Some caveats
I think most of what is needed for the 32-bit build can be installed via:
I had to reconstruct my msys2 when UPDATE: I have confirmed the build failure with the above linked sources. Downgrading to my older package ( |
@Biswa96 Unfortunately, the sample code I provided is not "simple". I have not created a "toy" program to reproduce. |
hmm could have happened if say one of the libraries you link to include say ncurses as we only have a static version of that it might have exported the PC symbol to said library but it is hard to say. can you try to build it with CFLAGS+=" -fcommon" CXXFLAGS+=" -fcommon" as i noticed this causes some packages that have previously linked without this error to suddenly throw a lot of multiple defines EDIT: damn i had a lot to "say" here xD |
Sadly, same exact error. Everything's* statically linked, so it'd have to be something that gloms ncurses on, which I see no clear evidence for. Here's a representative source compile w/ flags:
Here's the link (all the
*the exception being the SDL library |
Hmm at this point it might be prudent to just use LDFLAGS+=" -Wl,--allow-multiple-definition" untill we figure out where this symbol is comming from. |
Thanks, @revelator . I can chat w/ the code owner, but am more likely to use one of the other two workarounds available to me for now (the older build, or compiling out the usage of readline). I did some basic snooping and found the For readline that's not the case. I'm not familiar w/ how msys2 packages are built, but it seems most likely to be a change in how readline was built from the 8.0 sources vs. the 7.0 sources. FWIW, I found this repo and downloaded the 8.0 sources and checked #if !defined (__linux__) && !defined (NCURSES_VERSION)
# if defined (__EMX__) || defined (NEED_EXTERN_PC)
extern
# endif /* __EMX__ || NEED_EXTERN_PC */
char PC, *BC, *UP;
#endif /* !__linux__ && !NCURSES_VERSION */ To me, it would seem it's entirely dependent upon how readline was built. The code for this particular bit seems identical in the 7.0 source from here - again indicating it seems to be a compile-time issue for readline. In fact, if I were to throw out a wild guess... Did the definition of |
Indeed it does! It may well be that for the DLL builds, this isn't an issue, but that in static library builds it is. IIRC it may take a little more effort to export a global from a DLL build, but it's all too easy for static libraries. |
one experiment would be to try building readline without either ncurses or termcap :) it is entirely possible and depends only if you need the terminal capabilities in your program. If you dont then it should be an easy fix, though in the long run it would be best to find out why this happens so we dont run headlong into the same problem again. |
static builds are nice when they work but as you noticed there are some pitfalls like the one here and also knowing exactly which system libraries need to be linked to (static builds are newer really truely static anyway as they link to several system dll's but the compiler only links to a small number of system libraries by default so sometimes we do get these "not so fun" problems), i work with an offshot of the compilers here using TDM's patches which by default links to the static gcc runtimes so it does give me some perspective. |
dll builds load the symbols dynamically from the dll while static builds have the symbols linked into the application at runtime, so if say the symbol PC is not delared with the correct export for a static library then we get these kind of problems :). This is also the reason why static builds are sometimes several magnitudes bigger than the dll builds as all the symbols are linked into the resulting application. This was actually one of the major problems with TDM gcc as by default it linked in winpthreads statically but winpthreads also has problems with static exports so it caused me a huge headache trying to figure out why some stuff worked while several other projects failed miserably. the symbol in question is actually allmost correct for a static build but termcap has wrong exports for a dll build -> extern char PC; should have been __declspec(dllexport) char PC; and the static one should just be char PC: |
Hehe yeah.... at a long-time prior employer I did a lot of work on a large multi-platform codebase with a pretty sophisticated (and bespoke) build toolchain. Exporting globals from Windows DLLs is almost a "dark art" involving secret incantations and rare reagents. The fun part is the general difference in practices across platforms. Generally it seems the default *NIX approach is (or was) to statically link - it avoids "DLL Hell" and all sorts things, at the cost of larger executables and challenges to patch. E.g. if a security hole is found in termcap any app statically linked to it needs a rebuild to get the patch. Windows tends to favor shared library linkages, inviting DLL Hell but getting smaller individual app sizes, easier patches outside every app needing to rebuild. Mac apps seem to try to split the middle, but can't decide on .framework, .dylib, .so, or whatever lol. So when you have portable code across compilers, platforms, and target linkages, things get pretty ugly pretty fast when you have to herd the cats. There's not a universal standard way to deal with all those combinations of sources and targets AFAIK. Been a while since those things were the daily grind though! Maybe things are changing. |
its becoming more standardized that is for sure :) gcc has had a lot of hardening lately so things which would normally build no problem no longer does. one such is fortran which added more strictness at about version 8 i think gcc itself also became more strict and now errors out on things that would previously just had been warnings. personally i like clang though im a bit partial with rust (a bytecode compiler dependant on a bytecode compiler just using a different syntax as if things were not advanced enough as is huh...). |
btw i just noticed -Wl,--dynamicbase,--nxcompat,--no-seh if using binutils-2.36 these flags are no longer nessesary as it now defaults to having aslr and dep on. the --no-seh flag might still be needed though. I guess msys2 needs an update ;) |
I confirm the issue. This is what I get :-(
|
why not linking readline with ncurses instead? |
at some point i think it did but it was reverted because of some other problems, try it out and see if everything works as expected :) |
I got around this when building some statically linked utility programs by rebuilding Termcap with the PC variable renamed to TERMCAP_PC (there's 4 places, 2 in |
This work well. Thanks. |
We have to use dynamic link because static Link with readline will hit into MSYS2 issue here. msys2/MINGW-packages#8105
Hopefully this issue can be fixed so that avrdude can use readline properly with MSYS2 mingw32/64. |
I'm working on my static utilities again, and unfortunately this is not fixed. I still get multiple definition errors refering to the PC variable when linking readline with anything (found when building PCRE2). This also still breaks when something links both readline and NCurses (like gettext does). |
This used to work when using the package
mingw-w64-i686-readline-7.0.005-1-any.pkg.tar.xz
.Now, when upgrading to the latest (
mingw-w64-i686-readline-8.0.004-2-any.pkg.tar.zst
), linking both of these libraries results in an error fromld
:The text was updated successfully, but these errors were encountered: