I am having a compile-time issue which I have reduced to the following test case. I wish to call a C++ routine from fortran and have the C++ routine be MPI aware.
Consider the following sample code,
Fortran main:
! -- main.f90
program main
implicit none
external return_three
integer return_three
write(*,*) return_three()
end program main
C++ subroutine:
// -- subs.cpp
#include <mpi.h>
extern "C"
{
int return_three_();
}
int return_three_()
{
return 3;
}
Note that, for the problem to reproduce, I only need to include mpi.h.
Compiling with GCC 5.3 and OpenMPI 1.10.1 (I checked GCC 4.8 and PGI 15.10 too) gives the following problem during linking:
% mpic++ -c subs.cpp
% mpifort -c main.f90
% mpifort -o main subs.o main.o -lstdc++ -lgcc_s
subs.o: In function `MPI::Intracomm::Intracomm()':
subs.cpp:(.text._ZN3MPI9IntracommC2Ev[_ZN3MPI9IntracommC5Ev]+0x14): undefined reference to `MPI::Comm::Comm()'
subs.o: In function `MPI::Intracomm::Intracomm(ompi_communicator_t*)':
subs.cpp:(.text._ZN3MPI9IntracommC2EP19ompi_communicator_t[_ZN3MPI9IntracommC5EP19ompi_communicator_t]+0x19): undefined reference to `MPI::Comm::Comm()'
subs.o: In function `MPI::Op::Init(void (*)(void const*, void*, int, MPI::Datatype const&), bool)':
subs.cpp:(.text._ZN3MPI2Op4InitEPFvPKvPviRKNS_8DatatypeEEb[_ZN3MPI2Op4InitEPFvPKvPviRKNS_8DatatypeEEb]+0x24): undefined reference to `ompi_mpi_cxx_op_intercept'
subs.o:(.rodata._ZTVN3MPI3WinE[_ZTVN3MPI3WinE]+0x48): undefined reference to `MPI::Win::Free()'
subs.o:(.rodata._ZTVN3MPI8DatatypeE[_ZTVN3MPI8DatatypeE]+0x78): undefined reference to `MPI::Datatype::Free()'
collect2: error: ld returned 1 exit status
It seems to me like mpifort is missing some C++-related libraries. It's my understanding that mpifort should be used to compile a fortran main program, though. The problem doesn't occur with Intel 16.0 compiled against OpenMPI 1.10.1.
My questions are:
What's going on here? Why is Intel able to handle this sample code and PGI/GCC is not?
Is there a portable way to include C++ subroutines with MPI in a fortran code?
(if possible) Is there an easy way to fix my current problem? I'm trying to compile a package on my machine, so it'd be best if I could just add -lmagicfix or something.
I was able to compile your code with GCC 5.3.0 and openMPI 1.10.2 by adding -lmpi_cxx in the final step:
% mpic++ -c subs.cpp
% mpifort -c main.f90
% mpifort -o main main.o subs.o -lstdc++ -lmpi_cxx
The reason is that the openMPI wrapper compilers mpifort and mpic++ link to different MPI libraries. You can check this with the -showme:libs option:
% mpifort -showme:libs
mpi_usempif08 mpi_usempi_ignore_tkr mpi_mpifh mpi
% mpic++ -showme:libs
mpi_cxx mpi
So in order to use the C++ MPI library, you have to tell mpifort explicitly to link to it.
Related
I am working on a large mixed-language code in Fortran 1990 and C++ 11. I recently compiled on a new platform with intel compilers (which I have successfully used before), specifically Intel Version 19.1.1.217.
I have boiled the issue down to a simple test:
f.F90
subroutine ff()
implicit none
call system('echo y')
end subroutine ff
main.cc
#include <iostream>
extern "C"
{
void ff_(void);
}
int main(void)
{
ff_();
return 0;
}
I have emulated exactly how my code is built, which boils down to this:
mpif90 -f90=ifort -c f.F90 -o f.o
mpicxx -cxx=icpc -c main.cc -o main.o
mpicxx -cxx=icpc main.o f.o -L/software/intel/2020.1/compilers_and_libraries/linux/lib/intel64 -lifcore
...after which I get the following:
f.o: In function `ff_':
f.F90:(.text+0xd): undefined reference to `system_'
I am aware that calls to system() are not part of the stardard, but I can successfully compile and run the following with no problem:
p.F90:
program ff
implicit none
call system('echo y')
end program
mpif90 -f90=ifort p.f90 -o pexe && ./pexe
y
This suggests to me that using mpif90 -f90=ifort is imlicitly telling the linker to link in some extra libraries, but running ldd on the resulting executable shows a subset of the libraries linked in when I compile a simple C++ program.
What do I need to link to stop this error?
Well, I stumbled upon the solution immediately after asking this question. By using mpif90 -f90=ifort -v (source files) I was able to see everything that was being linked, and tried each library one at a time until it worked.
I am getting below linking error while compiling a simple piece of code using pthread.
The system i am working on is x86_64 (gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11) and am compiling as -
gcc -lpthread ~/temp/temp.cpp -lrt -L"/usr/lib/x86_64-redhat-linux5E/lib64/".
Its evident that the problem is with pthread library. So i have two questions.
Q1. is it fine to use x64 pthread libs with x86 code. (In this piece of code it doesnt matter but it does in my usage) (I guess its not but how might i differentiate between x64 and x86 libs?)
Q2. i see pthread and lrt both are present at /usr/lib but even if i give that path it says -lpthread not found.
What am i missing here? Thanks for your help.
Error :
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o: In function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
/tmp/cc2GQOUf.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status
Code :
#include <stdio.h>
#include <pthread.h>
int main()
{
pthread_t f1_thread;
return 0;
}
In compilation phase,compiler can use gcc or g++,but g++ will call gcc command automatically.But in link phase,linker can use g++ or gcc -lstdc++.Because the gcc command cannot link with the libraries that be used by c++ program automatically, so usually use g++to complete the link.
So the command g++ -g -lpthread ~/temp/temp.cpp -o temp should be ok.
I have the problem of linking the HDF-EOS library to a Fortran90 program. I have compiled the library from source to a directory specified in $prefix. My simple compile command is:
gfortran -I$prefix/include -L$prefix/lib -Wl,-rpath -Wl,$prefix/lib -lhdfeos -lGctp -lmfhdf -ldf -lz -lsz -ljpeg tst.f90
When compiling, I get the following error:
undefined reference to `gdopen_'
In the program, which I am not supposed to change, the HDF-EOS library is used via the external keyword, e.g.
integer(kind=4), external :: gdopen
In the library, nm $prefix/lib/libhdfeos.a | grep gdopen gives me:
00000000000120c0 T gdopen
When compiling with -fno-underscoring, I get just a different error:
gfortran -fno-underscoring -I$prefix/include -L$prefix/lib -Wl,-rpath -Wl,$prefix/lib -lhdfeos -lGctp -lmfhdf -ldf -lz -lsz -ljpeg tst.f90
the error is then:
undefined reference to `gdopen'
Also, gfortran finds the libraries, otherwise it would complain. Is the error related to the underscore? What else can I try? I work on Fedora and gfortran version 4.7.2.
Yes, very likely to be caused by the underscore.
Try compiling with -fno-underscoring (https://gcc.gnu.org/onlinedocs/gfortran/Code-Gen-Options.html), but fixing it by a proper bind(C) interface would be better.
This tutorial (Did you read it before going here? Very easy to find even for a complete novice in the library, like me.) also states you should use -fno-underscoring.
Continue by implementing the rest what the tutorial recommends, including compiling with FC=$(HDF4_DIR)/bin/h4fc.
I should couple in linux one c++ code with old fortran code, where fortan is the main code. Im not expert in this area and I try to start with simple test, but still I cannot compile it. Maybe I'm stupid, but I cannot find a working example anywhere. I managed to compile fortran and c, when the linking can be done by ifort (need to use intel compiler later with the actual fortran code). But If I've understood right, with c++, the linking must be done by c++ compiler (g++).
So what do I do wrong here:
My FORTRAN test code "ftest.f":
PROGRAM MAIN
IMPLICIT NONE
INTEGER I
write(*,*) "hello fortran1"
CALL ctest()
write(*,*) "hello fortran2"
END PROGRAM
And C++ code "ctest.cpp"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
extern "C" void ctest_();
void ctest_(){
int i;
// std::cout << "hello c \n";
printf("hello c\n");
}
I try to compile with the following:
ifort -c ftest.f
g++ -c ctest.cpp
g++ -ldl -lm -limf -L -l -lifcore ctest.o ftest.o
And I get an error:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
So what should I do to success with linking this program?
Your main (entry) is in Fortran part, so one way to solve it is to to use ifort linker instead of g++ (that would also link ifcore automatically)
ifort ctest.o ftest.o ... -lstdc++
So looks like I truested too much on one page telling me that I have to use c++ compiler for linking. Earlier just always something else was wrong when trying to link by ifort.
So using ifort with -lstdc++ is really enough with the current version of my test code. Earlier just something else was wrong.
Thank you very much once again, I wish you all the best for your own projects!
I'm trying to enable OpenMPI on Ubuntu using CodeBlocks. I have already downloaded it using:
sudo apt-get install -y autotools-dev g++ build-essential
openmpi1.6-bin openmpi1.6-doc libopenmpi1.6-dev
Afterwards I tried to run the following code:
#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv)
{
int size, rank;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
printf("SIZE = %d RANK = %d\n",size,rank);
MPI_Finalize();
return(0);
}
But I got this error:
fatal error: mpi.h: No such file or directory
Then I changed the c++ compiler from g++ to mpicxx as it's recommended here: FAQ: Compiling MPI.
But when I try to run my code now, I get the following bunch of errors:
openmpi.cpp|| undefined reference to `MPI_Init'|
openmpi.cpp|| undefined reference to `ompi_mpi_comm_world'|
openmpi.cpp|| undefined reference to `MPI_Comm_size'|
openmpi.cpp|| undefined reference to `ompi_mpi_comm_world'|
openmpi.cpp|| undefined reference to `MPI_Comm_rank'|
openmpi.cpp|| undefined reference to `MPI_Finalize'|
[...]
I assume, I have to add the Path or link the library, but I'm not sure how to achieve this. I also don't know where OpenMPI has been installed on my machine.
I have downloaded the folder from the website, as well, if that can help.
Update
After adding mpicxx to the linker and -pthread -L/opt/openmpi/lib -lmpi_cxx -lmpi -ldl -lm -Wl,--export-dynamic -lrt -lnsl -lutil -lm -ldl as additional flags, I finally can compile the code.
But now I get another error:
[[INVALID],INVALID] ORTE_ERROR_LOG: A system-required executable either could not be found or was not executable by this user in file ess_singleton_module_c at line 231
[...]
Soory! You were supposed to get help about:
orte_init:startup:internal-failure
But I couldn't open the file:
/usr/share/openmpi/help-orte-runtime: No such file or directory.
Most MPI libraries come with special compiler wrappers, e.g.:
mpicc for the C compiler;
mpic++/mpiCC/mpicxx for the C++ compiler;
mpif77/mpif90/mpif95 for the Fortran compiler;
other distribution-specific wrappers, e.g. mpiicc for Intel MPI library with Intel C Compiler.
These wrappers provide all options that are needed by the compiler in order to find the include files and link the proper libraries.
Therefore you have to update your project settings and change both the compiler and the linker to mpicxx.
Another option would be to run the following command:
mpicxx -showme:link
It will give you a list of options that you should add to the linker flags in your project's settings in order to properly link the executable with Open MPI.