Linking gnu libraries c++ and fortran - gcc

I have spent the day searching for an answer to what should be a simple problem. I am building a c++ program to call a fairly large amount of existing fortran. I started by changing the fortran main to a subroutine and then called it with a simple c++ main. My steps look like:
gfortran -c f1.f90 f2.f90 ......
g++ -c mn.cpp
gfortran -lstdc++ -o prog.exe mn.o f1.o ....
mn.cpp started out looking like the code below, and the above steps do work ok. I get a host of linker errors if I try to link with:
g++ -lgfortran (this never works!)
Next, I tried to instantiate a simple array class (remove the 2 commented lines). This produced linker errors concerning gxx_personality_seh0, vtable, and operator new.I get similar errors if I just create an array of doubles with new (remove comment), and if I remove the call to the fortran program completely (still linking with gfortran). Obviously, -lstdc++ does not bring in all the libraries needed. Which libraries are needed and how can I get it to link them?
I am using Windows 7 with Cygwin. The libraries it links are in ...lib/x86_64-pc-cygwin/4.9.3. I can post the linker output if it would be helpful.
mn.cpp which works (code commented out) is below:
#include <string.h>
#include <stdlib.h>
//#include "array.h"
extern "C" {
void mnf90_(const char*,int);
}
int main(int argc, char* argv[]){
// Array2D A; // first derivative
static const char *feos = "d/fld9x.dat";
int npoint = 20;
// double *xc = new double[npoint];
mnf90_(feos,strlen(feos));
}

Related

GCC builtin functions - 2003 vs 2019 behaviour

At page 14 of the book "Introduction to GCC" by Brian Gough, the author wants to show a linker error due to not supplying gcc with the libm library, where the code for the function sqrt resides:
$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function ‘main’:
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sqrt’
The file calc.c (where the functionsqrt is invoked) is this:
#include <math.h>
#include <stdio.h>
int main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This book is from 2003.
On my current Ubuntu Linux 18, I can't reproduce the link error: it links and works, printing the correct result:
$ ./calc
1.414214
I found with ldd calc that the libm.so shared library is not invoked at runtime. Nor of course is the static library libm.a involved here.
So how does gcc deal with the function sqrt? I found that in this case it uses the sqrt GCC built-in function.
Its code gets inserted in the calc.o object file at compile time. So no "undefined reference" error.
First question: this the whole story or am I missing something?
Second question: why did this behavior regarding the built-in functions of GCC change so much between 2003 (when the book was written) and now? (Practically invalidating the whole example, it seems to me)
Third question: why does the author make his examples (e.g.$ gcc -Wall calc.c -lm -o cal) implying that the static library libc.a will be used, when in reality in Linux that syntax invokes the dynamic library libm.so? Is this specific to Linux and not to GNU GCC? What am I mising?
I think this is due to optimization of a constant value. Modern GCC can compute exact value of sqrt (2.0). If you force it not to use the built-ins with -fno-builtin, it will still fail to link. Also, if you change the code a little bit so that the argument to sqrt() is not literal, it will fail to link:
#include <math.h>
#include <stdio.h>
double t = 2.0;
int main (void)
{
double x = sqrt (t);
printf ("The square root of 2.0 is %f\n", x);
return 0;
}
This produces link error:
> gcc -o test test.c
/usr/bin/ld: /tmp/ccLjHnQx.o: in function `main':
test.c:(.text+0x11): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
Regarding your 3rd question, -lm does not imply static library, AFAIK.

How to find hanging LLVM optimization pass?

I've written an LLVM pass that replaces a few store instructions with calls to a function that perform some book-keeping, and then performs the store in a special way. It works fine when I compile with -O0, but I can only guarantee the functionality of my pass when using -O3. When I compile with -O3(or -O1/-O2), it completes my pass successfully, and then hangs in some later optimization stage. Is there a way to discover which optimization pass is hanging / why?
Just so I don't have to provide it later, here is my code and my compile line.
clang++-5.0 -std=c++11 -Xclang -load -Xclang ../../plugin/build/mylib.so single_param.cc -c -I ../../libs/ -S -emit-llvm -O3
The problem is not in code generation because I'm only generating bitcode. I noticed that stores in -O3 (without my pass) include alias information, and I thought that since I'm deleting these instructions, some later optimization using this alias information might encounter some trouble, so I turned off most of the alias analysis using -fno-strict-aliasing
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
void __attribute__((noinline)) f(int *n){
*n = *n + 1;
}
int main(){
int a = 4;
f(&a);
return a;
}
The way I was able to find the pass that was stalling was by turning remarks on with
-Rpass=.* -Rpass-missed=.* -Rpass-analysis=.*
I found that the only optimization pass giving remarks was tail call optimization, so I turned it off. I later found the problem with my code, but this is how I found the problem I was causing.

mingw C++ won't compile j0 funciton

I'm trying to compile a program on Windows using MingW (msys2) and it fails with the j0 function. On Linux it compiles no problem. It seems to hate when I use the -std=c++11 flag on the compiler. How can I get this to compile properly and with the -std=c++11 flag on?
Sample code:
#include <cmath>
int main( int argc, char *argv[] )
{
float test = j0( 5 );
}
Output
$ g++ -std=c++11 test.cpp -o test
test.cpp: In function 'int main(int, char**)':
test.cpp:6:21: error: 'j0' was not declared in this scope
float test = j0( 5 );
Apparently, MinGW defines the Bessel functions only when __STRICT_ANSI__ is not defined, and it is defined when -std=c++11 is specified. I was able to get your code to compile in MinGW by adding #undef __STRICT_ANSI__ at the top of the file. See https://sourceforge.net/p/mingw-w64/feature-requests/68/
You might also try -std=gnu++11 instead. See https://stackoverflow.com/a/19667112/10077

gcc optimizations: how to deal with macro expantion in strncmp & other functions

Take this sample code:
#include <string.h>
#define STRcommaLEN(str) (str), (sizeof(str)-1)
int main() {
const char * b = "string2";
const char * c = "string3";
strncmp(b, STRcommaLEN(c));
}
If you don't use optimizations in GCC, all is fine, but if you add -O1 and above, as in gcc -E -std=gnu99 -Wall -Wextra -c -I/usr/local/include -O1 sample.c, strncmp becomes a macro, and in preprocessing stage STRcommaLen is not expanded. In fact in resulting "code" strncmp's arguments are completely stripped.
I know if I add #define NEWstrncmp(a, b) strncmp (a, b) and use it instead, the problem goes away. However, mapping your own functions to every standard function that may become a macro doesn't seem like a great solution.
I tried finding the specific optimization that is responsible for it and failed. In fact if I replace -O1 with all the flags that it enables according to man gcc, the problem goes away. My conclusion is that -O1 adds some optimizations that are not controlled by flags and this is one of them.
How would you deal with this issue in a generic way? There may be some macro magic I am not familiar with or compiler flags I haven't looked at? We have many macros and a substantial code base - this code is just written to demonstrate one example.
Btw, GCC version/platform is gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5).
Thanks,
Alen
You correctly noted that
in preprocessing stage STRcommaLen is not expanded
- more precisely, not before the strncmp macro gets expanded. This inevitably leads to an error you probably overlooked or forgot to mention:
sample.c:7:30: error: macro "strncmp" requires 3 arguments, but only 2 given
Your conclusion
that -O1 adds some optimizations that are not controlled by flags and
this is one of them
is also right - this is controlled by the macro __OPTIMIZE__ which apparently gets set by -O1.
If I'd do something like that (which I probably wouldn't, in respect of the pitfall you demonstrated by using sizeof a char *), I'd still choose
mapping your own functions to every standard function that may become
a macro
- but rather like
#include <string.h>
#define STRNCMP(s1, s2) strncmp(s1, s2, sizeof(s2)-1)
int main()
{
const char b[] = "string2";
const char c[] = "string3";
STRNCMP(b, c);
}

A linking error related to 'gcc' and '-lm'

Well, I think my problem is a little bit interesting and I want to understand what's happening on my Ubuntu box.
I compiled and linked the following useless piece of code with gcc -lm -o useless useless.c:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * 440 * ((float) 1/44100)));
return(0);
}
So far so good. But when I change to this:
/* File useless.c */
#include <stdio.h>
#include <math.h>
int main()
{
int freq = 440;
int sample = (int)(0.75 * 32768.0 * sin(2 * 3.14 * freq * ((float) 1/44100)));
return(0);
}
And I try to compile using the same command line, and gcc responds:
/tmp/cctM0k56.o: In function `main':
ao_example3.c:(.text+0x29): undefined reference to `sin'
collect2: ld returned 1 exit status
And it stops. What is happening? Why can't I compile that way?
I also tried a sudo ldconfig -v without success.
There are two different things going on here.
For the first example, the compiler doesn't generate a call to sin. It sees that the argument is a constant expression, so it replaces the sin(...) call with the result of the expression, and the math library isn't needed. It will work just as well without the -lm. (But you shouldn't count on that; it's not always obvious when the compiler will perform this kind of optimization and when it won't.)
(If you compile with
gcc -S useless.c
and take a look at useless.s, the generated assembly language listing, you can see that there's no call to sin.)
For the second example, you do need the -lm option -- but it needs to be at the end of the command line, or at least after the file (useless.c) that needs it:
gcc -o useless useless.c -lm
or
gcc useless.c -lm -o useless
The linker processes files in order, keeping track of unresolved symbols for each one (sin, referred to by useless.o), and then resolving them as it sees their definitions. If you put the -lm first, there are no unresolved symbols when it processes the math library; by the time it sees the call to sin in useless.o, it's too late.

Resources