[opensuse-packaging] Weird "undefined reference" only for TW x64
Dear all, First of all, a disclaimer, I am NOT a dev and I'm only packaging a few things when I need them on different computers or when I feel it could benefit other people than me (mainly sciency stuff). I've been trying to build a software that performs population genetics simulation: https://build.opensuse.org/package/show/home:flyos:science/Nemo The software has little dependencies and should be relatively easy to build, but I needed to switch the Makefile to g++-7 on my TW install, otherwise it fails. It also fails on OBS, but only on Tumbleweed x64 (succeeded on the 32bit version ?!). Here's the error when it fails: /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o: in function `TT_BDMI::store_data(BinaryStorageBuffer*)': ttbdmi.cc:(.text+0x421): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?), and why it would depend on the arch and version of GCC... At least out of curiosity, if anybody has an idea of what is going on here, I would appreciate any help! Cheers, Pierre. -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Wednesday 2020-04-01 18:24, Pierre wrote:
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow
I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?)
Your .o file does not contain the function in question. abuild@a4:~/rpmbuild/BUILD/Nemo-2.3.51> nm -C src/binarystoragebuffer.o | grep ::store -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
So, why is this happening only in TW x64 (with GCC9) and how can I fix it? Le mercredi 1 avril 2020, 19:18:35 CEST Jan Engelhardt a écrit :
On Wednesday 2020-04-01 18:24, Pierre wrote:
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow
I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?)
Your .o file does not contain the function in question.
abuild@a4:~/rpmbuild/BUILD/Nemo-2.3.51> nm -C src/binarystoragebuffer.o | grep ::store
-- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On 4/1/2020 11:18, Jan Engelhardt wrote:
On Wednesday 2020-04-01 18:24, Pierre wrote:
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow
I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?)
Your .o file does not contain the function in question.
abuild@a4:~/rpmbuild/BUILD/Nemo-2.3.51> nm -C src/binarystoragebuffer.o | grep ::store
The reason for that being that store() is defined "inline" in binarystoragebuffer.c. Inline means to replace the function call with the body of the function wherever it is called. This means you need to have the body of the function in the header file (binarystoragebuffer.h), not a source file. By the time the source file is compiled and linking is happening, it is too late to inline a function. So I'd guess that in the other versions gcc has ignored the inline and treated it as a normal function, whereas the Tumbleweed x86_64 has honored the inline and dropped the function from the object file. To fix it, the simplest way is to remove "inline" from the function definition. You could also move the inline definition to the header file, but as demonstrated this function is fairly unlikely to actually be inlined by the compiler. -- Jason Craig -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Mittwoch, 1. April 2020 19:44:04 CEST Jason Craig wrote:
On Wednesday 2020-04-01 18:24, Pierre wrote:
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow
I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?)
Your .o file does not contain the function in question.
abuild@a4:~/rpmbuild/BUILD/Nemo-2.3.51> nm -C src/binarystoragebuffer.o | grep ::store The reason for that being that store() is defined "inline" in binarystoragebuffer.c. Inline means to replace the function call with
On 4/1/2020 11:18, Jan Engelhardt wrote: the body of the function wherever it is called. This means you need to have the body of the function in the header file (binarystoragebuffer.h), not a source file. By the time the source file is compiled and linking is happening, it is too late to inline a function.
So I'd guess that in the other versions gcc has ignored the inline and treated it as a normal function, whereas the Tumbleweed x86_64 has honored the inline and dropped the function from the object file.
To fix it, the simplest way is to remove "inline" from the function definition. You could also move the inline definition to the header file, but as demonstrated this function is fairly unlikely to actually be inlined by the compiler.
This seems to be a regression, as it deviates from GCCs own documentation: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
The three types of inlining behave similarly in two important cases: [...], and when *a function is first declared without using the inline keyword and then is defined with inline*, like this:
extern int inc (int *a); inline int inc (int *a) {
return (*a)++;
}
In both of these common cases, the program behaves the same as if you had not used the inline keyword, except for its speed.
This may be related to LTO. Kind regards, Stefan -- Stefan Brüns / Bergstraße 21 / 52062 Aachen home: +49 241 53809034 mobile: +49 151 50412019
Am 01.04.20 um 20:14 schrieb Stefan Brüns:
On Mittwoch, 1. April 2020 19:44:04 CEST Jason Craig wrote:
The reason for that being that store() is defined "inline" in binarystoragebuffer.c. Inline means to replace the function call with the body of the function wherever it is called. This means you need to have the body of the function in the header file (binarystoragebuffer.h), not a source file. By the time the source file is compiled and linking is happening, it is too late to inline a function.
So I'd guess that in the other versions gcc has ignored the inline and treated it as a normal function, whereas the Tumbleweed x86_64 has honored the inline and dropped the function from the object file.
To fix it, the simplest way is to remove "inline" from the function definition. You could also move the inline definition to the header file, but as demonstrated this function is fairly unlikely to actually be inlined by the compiler.
This seems to be a regression, as it deviates from GCCs own documentation: https://gcc.gnu.org/onlinedocs/gcc/Inline.html
I thought so too, but looking at the standard seems to indicate that GCC is allowed to do this (http://eel.is/c++draft/dcl.inline#5): If a function or variable with external or module linkage is declared inline in one definition domain, an inline declaration of it shall be reachable from the end of every definition domain in which it is declared; no diagnostic is required. "Definition domain" is what used to be a "translation unit", the latest published draft [1] still uses that term. Of course GCC can provide guarantees beyond the requirements of the standard, if the developers want to, since "no diagnostic is required." Kind regards, Aaron [1] https://github.com/cplusplus/draft/blob/master/papers/n4835.pdf -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
So, if I understand your comment, the code currently have binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes) binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes); And it would be better to either have: binarystoragebuffer.cc: void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes) binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes); Or: binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes) binarystoragebuffer.h: inline void store (void* stream, unsigned int nb_bytes); Am I understanding this right? Should I contact the dev about this? Thank you all for your help! Pierre Le mercredi 1 avril 2020, 19:44:04 CEST Jason Craig a écrit :
On 4/1/2020 11:18, Jan Engelhardt wrote:
On Wednesday 2020-04-01 18:24, Pierre wrote:
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x46e): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x48b): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4a8): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: ttbdmi.cc:(.text+0x4c5): undefined reference to `BinaryStorageBuffer::store(void*, unsigned int)' /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld: src/ttbdmi.o:ttbdmi.cc:(.text+0x4e2): more undefined references to `BinaryStorageBuffer::store(void*, unsigned int)' follow
I don't understand why the "undefined reference" is coming up here (binarystoragebuffer.cc has been compiled into an .o object and should link without a problem?)
Your .o file does not contain the function in question.
abuild@a4:~/rpmbuild/BUILD/Nemo-2.3.51> nm -C src/binarystoragebuffer.o | grep ::store
The reason for that being that store() is defined "inline" in binarystoragebuffer.c. Inline means to replace the function call with the body of the function wherever it is called. This means you need to have the body of the function in the header file (binarystoragebuffer.h), not a source file. By the time the source file is compiled and linking is happening, it is too late to inline a function.
So I'd guess that in the other versions gcc has ignored the inline and treated it as a normal function, whereas the Tumbleweed x86_64 has honored the inline and dropped the function from the object file.
To fix it, the simplest way is to remove "inline" from the function definition. You could also move the inline definition to the header file, but as demonstrated this function is fairly unlikely to actually be inlined by the compiler.
-- Jason Craig
-- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On 4/1/2020 12:23, Pierre wrote:
So, if I understand your comment, the code currently have
binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes);
And it would be better to either have:
binarystoragebuffer.cc: void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes);
That would be my choice, but I'm sure the developer is worried about performance and is trying to inline as much as possible.
Or:
binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: inline void store (void* stream, unsigned int nb_bytes);
Almost. The function wouldn't be in binarystoragebuffer.cc at all anymore. I can send you patches later on for either option, but first I have to eat....
Am I understanding this right? Should I contact the dev about this?
Yeah. You can add a patch for it to work correctly on OBS, but ideally upstream (the dev) would make the code change there and you could drop the patch at that point.
Thank you all for your help! Pierre
thanks, -- Jason Craig -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
Am 02.04.20 um 00:39 schrieb Jason Craig:
That would be my choice, but I'm sure the developer is worried about performance and is trying to inline as much as possible.
In modern compilers, the "inline" keyword has no influence on inlining decisions. They have a simple cost/benefit model where the cost is basically the length of the function to be inlined, and the benefit is determined by the hotness of the execution path. If no profiling information is available, hotness is usually assumed to be constant, except that it's a bit higher in loops, and even higher in nested loops, and lower in paths that lead to exceptions or calls to noreturn functions like abort or exit. So removing the inline keyword doesn't change anything about inlining. Still, without LTO the definition must be available for inlining, although at least on openSUSE that's not a concern since LTO is enabled by default now. If you're really sure you want a function to be inlined which the compiler considers too long, you can still add non-standard attributes like __attribute__((always_inline)) to force it. You could also use __attribute__((hot)), but my impression is that compilers ignore it. Kind regards, Aaron -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On 4/1/2020 16:39, Jason Craig wrote: ...
Am I understanding this right? Should I contact the dev about this?
Yeah. You can add a patch for it to work correctly on OBS, but ideally upstream (the dev) would make the code change there and you could drop the patch at that point.
Ugh, nevermind about the patch. Turns out trying to either remove the inline or move it to the header doesn't work correctly because the developer has included binarystoragebuffer.cc in several other .cc files (but also still built into an object file). I don't understand the developer's intent and so I don't know how to fix it. You should report the problem upstream. -- Jason Craig -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
Hi, OK, then I'll report upstream, seems it is not possible to come up with an easy fix (I mean, if you guys can't, I certainly can't). Thank you very much for your help! Cheers, Pierre Le jeudi 2 avril 2020, 03:48:39 CEST Jason Craig a écrit :
On 4/1/2020 16:39, Jason Craig wrote: ...
Am I understanding this right? Should I contact the dev about this?
Yeah. You can add a patch for it to work correctly on OBS, but ideally upstream (the dev) would make the code change there and you could drop the patch at that point.
Ugh, nevermind about the patch. Turns out trying to either remove the inline or move it to the header doesn't work correctly because the developer has included binarystoragebuffer.cc in several other .cc files (but also still built into an object file). I don't understand the developer's intent and so I don't know how to fix it. You should report the problem upstream.
-- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Thursday 2020-04-02 13:31, Pierre wrote:
Hi,
OK, then I'll report upstream, seems it is not possible to come up with an easy fix (I mean, if you guys can't, I certainly can't).
uh, just remove the "inline" keyword? -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
Jason and I tried, it doesn't work, unfortunately. It yields : /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/binarystoragebuffer.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : binarystoragebuffer.cc:(.text+0x0) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/individual.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : individual.cc:(.text+0x260) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/metapop.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : metapop.cc:(.text+0xa30) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici Sorry for the French, a wild guess is that the English version of "définitions multiples" would be... "multiple definitions"? Jason said in his last email:
Turns out trying to either remove the inline or move it to the header doesn't work correctly because the developer has included binarystoragebuffer.cc in several other .cc files (but also still built into an object file). I don't understand the developer's intent and so I don't know how to fix it. You should report the problem upstream.
Which I interpreted as "there is no easy fix, report to upstream". Cheers, Pierre Le jeudi 2 avril 2020, 13:55:20 CEST Jan Engelhardt a écrit :
On Thursday 2020-04-02 13:31, Pierre wrote:
Hi,
OK, then I'll report upstream, seems it is not possible to come up with an easy fix (I mean, if you guys can't, I certainly can't).
uh, just remove the "inline" keyword?
-- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Thu, 2 Apr 2020, Pierre wrote:
Jason and I tried, it doesn't work, unfortunately. It yields :
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/binarystoragebuffer.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : binarystoragebuffer.cc:(.text+0x0) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/individual.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : individual.cc:(.text+0x260) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/metapop.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : metapop.cc:(.text+0xa30) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici
Sorry for the French, a wild guess is that the English version of "définitions multiples" would be... "multiple definitions"?
As you said the .cc file is included in multiple places another fix would be to also include it from the file the orginal undefined reference is reported from. Richard.
Jason said in his last email:
Turns out trying to either remove the inline or move it to the header doesn't work correctly because the developer has included binarystoragebuffer.cc in several other .cc files (but also still built into an object file). I don't understand the developer's intent and so I don't know how to fix it. You should report the problem upstream.
Which I interpreted as "there is no easy fix, report to upstream".
Cheers, Pierre
Le jeudi 2 avril 2020, 13:55:20 CEST Jan Engelhardt a écrit :
On Thursday 2020-04-02 13:31, Pierre wrote:
Hi,
OK, then I'll report upstream, seems it is not possible to come up with an easy fix (I mean, if you guys can't, I certainly can't).
uh, just remove the "inline" keyword?
-- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
-- Richard Biener <rguenther@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)
On 4/2/2020 07:01, Richard Biener wrote:
On Thu, 2 Apr 2020, Pierre wrote:
Jason and I tried, it doesn't work, unfortunately. It yields :
/usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/binarystoragebuffer.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : binarystoragebuffer.cc:(.text+0x0) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/individual.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : individual.cc:(.text+0x260) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici /usr/lib64/gcc/x86_64-suse-linux/9/../../../../x86_64-suse-linux/bin/ld : src/metapop.o : dans la fonction « BinaryStorageBuffer::store(void*, unsigned int) » : metapop.cc:(.text+0xa30) : définitions multiples de « BinaryStorageBuffer::store(void*, unsigned int) »; src/binarydatasaver.o:binarydatasaver.cc:(.text+0x170) : défini pour la première fois ici
Sorry for the French, a wild guess is that the English version of "définitions multiples" would be... "multiple definitions"?
As you said the .cc file is included in multiple places another fix would be to also include it from the file the orginal undefined reference is reported from.
Richard.
That does indeed fix that undefined reference. Then another one springs up. And another one...seems like most of the sources use that function and only a couple #include the .cc file. Definitely something upstream needs to sort out. Preferably by removing the #includes to source files, but if the dev wants a confusing mess he is welcome to further it. -- Jason Craig -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Fri, Apr 3, 2020 at 1:13 PM Jason Craig <os-dev@jacraig.com> wrote:
Preferably by removing the #includes to source files, but if the dev wants a confusing mess he is welcome to further it.
Burn that with fire and run away..doesn't look like something that is well thought out, LTO or not. -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
Am 01.04.20 um 20:23 schrieb Pierre:
So, if I understand your comment, the code currently have
binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes);
Yes, that's a problem because of http://eel.is/c++draft/dcl.inline#5: If a function or variable with external or module linkage is declared inline in one definition domain, an inline declaration of it shall be reachable from the end of every definition domain in which it is declared; no diagnostic is required. The function is declared with (implicit) external linkage in the header file. Since binarystoragebuffer.cc (basically a "definition domain") contains an inline declaration, all other source files that include this header must have an inline declaration. That isn't satisfied. The last clause says that the compiler isn't required to diagnose this, that's why you see no compiler error.
And it would be better to either have:
binarystoragebuffer.cc: void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes);
Then neither declaration is inline, so this is fine.
Or:
binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: inline void store (void* stream, unsigned int nb_bytes);
This wouldn't violate the quoted requirement, but another requirement that used to be in the same clause but was moved in a recent change [1] to http://eel.is/c++draft/basic.def.odr#11: A definition of an inline function or variable shall be reachable from the end of every definition domain in which it is odr-used outside of a discarded statement. Since the function is inline, a definition (which is contained in binarystoragebuffer.cc only) should be reachable in every source file where it is used, but then we're back to your original issue: ttbdmi.cc also uses the function, but the definition isn't reachable from there. The proper solution with inlining would be to move the definition to the header, so binarystoragebuffer.cc: // nothing binarystoragebuffer.h: inline void store (void* stream, unsigned int nb_bytes) { ... } Why all this? Inlining (without LTO) obviously requires a definition to be available. If a function is supposed to be inlined in multiple source files, it must be defined in multiple source files, for example by putting it into a header. This means the definition would be emitted into the object file for every source file that includes the header! Luckily, the compiler is allowed to drop inline functions if they are either unused, or have been inlined into all uses. But that means that no object file is guaranteed to contain the inline function. So if a function is inline, the definition should be available in every source file it's used in, so that it can be emitted on demand. So put it in a header file, and ideally drop all non-definition declarations.
Should I contact the dev about this? This sounds like a reasonable thing to do.
Kind regards, Aaron [1] https://github.com/cplusplus/draft/commit/22d13485a2e40ea6f1ee3e943e66bb4300... -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
On Donnerstag, 2. April 2020 01:36:40 CEST Aaron Puchert wrote:
Am 01.04.20 um 20:23 schrieb Pierre:
So, if I understand your comment, the code currently have
binarystoragebuffer.cc: inline void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes)
binarystoragebuffer.h: void store (void* stream, unsigned int nb_bytes);
Yes, that's a problem because of http://eel.is/c++draft/dcl.inline#5:
If a function or variable with external or module linkage is declared inline in one definition domain, an inline declaration of it shall be reachable from the end of every definition domain in which it is declared; no diagnostic is required.
The function is declared with (implicit) external linkage in the header file. Since binarystoragebuffer.cc (basically a "definition domain") contains an inline declaration, all other source files that include this header must have an inline declaration. That isn't satisfied.
No, your diagnosis is wrong. The .cc file does not have a *inline* declaration. The note above does not apply. void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes); is a declaration. void BinaryStorageBuffer::store (void* stream, unsigned int nb_bytes) {...} is a definition, but it may be also a declaration. 1. declared (and defined) inline: --- inline void foo(int); inline void foo(int) { return; } --- 2. also declared (and defined) inline: --- inline void foo(int) { return; } --- 3. not declared inline: --- void foo(int) { return; } --- 4. also not declared inline: --- void foo(int); inline void foo(int) { return; } --- Regards, Stefan -- Stefan Brüns / Bergstraße 21 / 52062 Aachen home: +49 241 53809034 mobile: +49 151 50412019
Am 02.04.20 um 02:30 schrieb Stefan Brüns:
4. also not declared inline: --- void foo(int); inline void foo(int) { return; } ---
That's not what the standard says (http://eel.is/c++draft/dcl.inline#2): A function declaration ([dcl.fct], [class.mfct], [class.friend]) with an inline specifier declares an inline function. Further the compiler can assume that everybody who sees the first declaration also sees the second declaration because of the previously quoted http://eel.is/c++draft/dcl.inline#5: If a function or variable with external or module linkage is declared inline in one definition domain, an inline declaration of it shall be reachable from the end of every definition domain in which it is declared; no diagnostic is required. Kind regards, Aaron -- To unsubscribe, e-mail: opensuse-packaging+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse-packaging+owner@opensuse.org
participants (7)
-
Aaron Puchert
-
Cristian Rodríguez
-
Jan Engelhardt
-
Jason Craig
-
Pierre
-
Richard Biener
-
Stefan Brüns