4

I cannot figure out how to fix this linking problem in GCC.
I am running CodeBlocks 13.12, under Windows 8, GCC+MingWG 4.8.1.
I have created a project having two files:

main.c

#include <complex.h>
int main(void)  
{  
    double complex (*FUNC)(double complex) = conj;   
    return 0;  
}  

test.c

#include <complex.h>  
double complex (*CEXP)(double complex) = cexp;  
double complex (*CONJ)(double complex) = conj;  

When the project is compiled in CodeBlocks (I use the compiler option -std=c11, only),
an error results, saying: "Undefined reference to conj".

I think this is extrange, since the function conj is defined in complex.h, as function cexp is, but the reference to cexp seems to work well.

On the other hand, the error is not triggered for the reference to conj in file main.c.
(SORRY: It seems that the error is triggered in main.c, also)

Is this a particular issue of GCC?
How I must configure CodeBlocks to fix this problem?
Thanks in advance.

More information. The compiler window shows these lines in CodeBlocks:

mingw32-gcc.exe -Wall -g -std=c11 -g -std=c11 -c C:\Users\Machine\Desktop\myapp\myapp.c -o obj\Debug\myapp.o
mingw32-gcc.exe -Wall -g -std=c11 -g -std=c11 -c C:\Users\Machine\Desktop\myapp\test.c -o obj\Debug\test.o
mingw32-g++.exe -o bin\Debug\myapp.exe obj\Debug\myapp.o obj\Debug\test.o
obj\Debug\myapp.o: In function main': C:/Users/Machine/Desktop/myapp/myapp.c:9: undefined reference toconj' obj\Debug\test.o:test.c:(.data+0x4): undefined reference to `conj' collect2.exe: error: ld returned 1 exit status

ALSO: I've tried to write the option -lm in several places on CodeBlocks without any success (for example, in Settings/Compiler/Other options, or Settings/Compiler/Linker, or Project/Build options..., etc.).

MOREOVER: The function conj is defined as "inline" by MinGW32 in complex.h. I souspect that this could be the problem, but using option -fno-inline has not any effect.

NM program: By following the suggestion of o11c, I used the nm program. The following output is obtained:

<snip, not what was needed>
pablo1977
  • 4,281
  • 1
  • 15
  • 41
  • 1
    You may need to explicitly link against the math library (`-lm` flag). – Ismail Badawi Jun 27 '15 at 22:29
  • @IsmailBadawi: And how do I do that in CodeBlocks? I tried to add the -lm option in several places, but it does not work. – pablo1977 Jun 27 '15 at 22:38
  • I am not sure, but I think that it's a bug of MinGW, related to the inline definitions in complex.h. – pablo1977 Jun 28 '15 at 00:17
  • Neither `inline` or `extern inline` should lead to linker errors. Do you have the `nm` executable to list symbols in your `libm.dll` ? – o11c Jun 28 '15 at 00:43
  • @o11c: I run **nm** with parameter **-C** and obtained the output that is shown in the bottom of my question. I don't know if this is useful or correct. – pablo1977 Jun 28 '15 at 03:10
  • @o11c: I have not any libm.dll file. By running **nm libm.a** I obtain nothing. Just this: 00000000 b .bss 00000000 d .data 00000000 t .text – pablo1977 Jun 28 '15 at 03:20
  • @pablo1977 `nm` on your program is useless, we already know that. Since `libm` is a C library, `nm -C` is a no-op. `nm` on the library (`libm.a` is a static library, is that the only one you have for sure?) should be able to tell what is in it, with appropriate flags. It is quite concerning that there is no symbol output, how large is `libm.a`? On linux it is 2MB. – o11c Jun 28 '15 at 04:07
  • @pablo1977 also what website did you download mingw from? There is an old `mingw32` project (that does 32-bit only) and a newer `mingw-w64` project (that does both 32-bit and 64-bit). – o11c Jun 28 '15 at 04:09
  • See, this is a major failing of SO ... you are getting comments from well-meaning individuals who have most likely never used MinGW, and who don't know what they are talking about. FTR, `libm.a` does _absolutely nothing_ in MinGW; your issue is likely that you are not including appropriate headers -- `` _and_ `` in this case, or that you are using one of the critically broken `mingwrt-4.x` releases, which have been withdrawn by MinGW.org. You should be using `mingwrt-3.21.1`. – Keith Marshall Jun 28 '15 at 09:22
  • @KeithMarshall: As you can see in my pieces of code, the header is present. The library is nothing to do here, since the function "conj" is declared in . I tried #include'ing , without success. I also tried by adding the -lm compiling option, and nothing happens. – pablo1977 Jun 28 '15 at 13:56
  • Yes, I did notice you included ``; omitting it is not the problem, in this case -- using a version of `mingwrt` which laks an external implementation of `conj()` _is_ the problem. `libm.a`, or `-lm` is completely irrelevant; in MinGW it provides exactly one _utterly useless_ symbol, and _absolutely nothing_ of any value. – Keith Marshall Jun 28 '15 at 15:02

2 Answers2

4

Okay, I think I see where your problem is now; you are trying to take the entry-point addresses of conj() and cexp(), which works for cexp(), but not for conj(). The explanation is that cexp() is a real external function, for which you can obtain an address, but, if you are using a mingwrt-3.x predating mingwrt-3.21, (or any broken, and now withdrawn mingwrt-4.x release), conj() is implemented as __inline__, with no corresponding external implementation, so there is no way to get its address.

I've fixed this issue, in mingwrt-3.21, so you should ensure that you are using that, (preferably the mingwrt-3.21.1 release).

Keith Marshall
  • 1,980
  • 15
  • 19
  • Keith, the "inline" issue was my first guess, but other users told that inlining has nothing to do with the problem. On the other hand, creal and cimag are "inline", too, in mingw, but it seems that they are real external functions after all. I will try to reinstall mingw to the version you says. – pablo1977 Jun 28 '15 at 14:05
  • @pablo: Those who say inlining has nothing to do with the issue are ... shall we say "misguided"; it _is_ the very crux of the problem. See, you are trying to refer to `conj()` by address, but you cannot get an address for a function which does not actually exist as a stand-alone entity, but simply has its body expanded in line, at every point of use. Even "`extern inline`" doesn't magically ensure that an external implementation exists; it is incumbent on the developer to ensure that it is provided. – Keith Marshall Jun 28 '15 at 15:14
  • I think this is not incumbent on the developer. It's a library issue, since the identifier cproj is stablished in Standard libraries (C99 and C11) as a function, so, if the developer wants to declare a "pointer to function" object, by assigning the value "cproj", for example, this assignment would have to work without any surprises to the developer. My MinGW installation seems to be some TDM-GCC 4.0.*. I will try another version. – pablo1977 Jun 28 '15 at 16:12
  • Suggest OP simply wraps the functions in something not inlined. – abligh Jun 28 '15 at 18:22
  • Keith: I've installed 3.* version of MinGW32 as you adviced and **the problem is fixed**. So I choose your answer. I think the implementation of compiler+libraries is responsible for this issue: it has to consider a funcion of a standard library "as if" it had an actual address, according to the Standard C specs. It must not be surprises for the developer. On the other hand, it's also a common assumption for developers, as discussed in: [Do inline functions have an address?](http://stackoverflow.com/questions/3318322/do-inline-functions-have-addresses). – pablo1977 Jun 28 '15 at 23:57
  • @pablo, By "developer", I meant the developer of the library, so yes, it is incumbent on him ... in this case, the guy who developed `mingwrt` before me got it wrong, and I've fixed it. – Keith Marshall Jun 29 '15 at 12:32
  • @pablo, TDM-GCC is _not_ MinGW. – Keith Marshall Jun 30 '15 at 14:26
  • @pablo, the [link](http://stackoverflow.com/questions/3318322/do-inline-functions-have-addresses) you cited refers, primarily, to C++ inline methods; OTOH, `conj()` is a GCC `__inline__ __attribute__((__always_inline__))` _C_ function; in mingwrt, it is implemented as such _directly_ within ``. Such an implementation _cannot_ generate an `extern` copy -- every translation unit including the header would provide a copy, leading to multiple definition errors at link time. Thus, it is incumbent on the (mingwrt) developer to provide a _separate_ `extern` implementation. – Keith Marshall Jun 30 '15 at 16:14
  • @abligh, It is all very well to suggest that OP wraps the implementation in something which is not inlined. Unfortunately, that doesn't fix the underlying problem, whereas, `mingwrt-3.21` _does_. Better, by far, to suggest that OP uses the up-to-date version of the library, as he (sensibly) now does. – Keith Marshall Jun 30 '15 at 16:18
  • @KeithMarshall absolutely - I simply meant as a workaround if he needed it work compile with older versions too. – abligh Jun 30 '15 at 17:09
0

I turned my comment on Keith Marshall's answer into an answer as well (as it's too long for a comment):

As per Keith Marshall's answer, the problem is that they are inline, and that gcc is not producing a non-inlined version.

To get around this, add

static double complex conj_ (double complex a)
{
    return conj (a);
}

etc. - you can take the addresses of these, and if ever conj becomes non-inline, the function should optimise out to a simple address of conj.

abligh
  • 24,573
  • 4
  • 47
  • 84
  • Well, I have already done something similar, and worked. Anyway, I don't know if to choose this answer as the rigth one, because I still think that me, as a developer, must rely in the believe that **standard library functions** behaves **as if** they were implemented as not inlined functions. In particular, a **function designator** shall be converted to "pointer to function", according to Standard C11.6.3.2.1/4, so the address of the function designator must exists, not matter how. – pablo1977 Jun 28 '15 at 22:04
  • As I've already pointed out, in my own answer, this issue is fixed in mingwrt-3.21 and later releases of the 3.x series. This is a workaround, rather than an answer, and is no longer required. – Keith Marshall Jun 29 '15 at 01:36
  • @KeithMarshall yep - I meant as a workaround in case it's necessary to provide buidl time compatibility with older versions. – abligh Jun 30 '15 at 17:09