f2py does not find any compiler - python

I have the NAG Fortran compiler installed. I can compile Fortran code by calling nagfor -o helloworld helloworld.f90. If I run f2py with f2py -c -m helloworld helloworld.f90 --fcompiler=nagfor nothing happens. Additionally, if I just run f2py nothing happens. f2py --help-fcompiler gives no output.
I have Windows 7 installed and use the the Anaconda Python distribution. Any idea how I should address this problem?

Following Ian`s comments and this post I managed to run f2py (unfortunately only with the GNU Fortran compiler).
I had to change line 337 in C:\Loopy\Lib\site-packages\numpy\distutils\fcompiler\gnu.py to:
pass #raise NotImplementedError("Only MS compiler supported with gfortran on win64")
Additionally I use C:\Loopy\Scripts\f2py.py.

It's unusual that you aren't seeing any error output at all.
That makes it sound like you're calling something else.
Make sure Anaconda's scripts directory on your path and that you don't have some sort of script in your current directory called f2py.
Depending on how you have your computer is set up to interpret file types, you may need to run something like python f2py.py with the rest of the arguments the same.
If you're using Anaconda, you should already have a copy of gfortran intsalled too.
If you want to use that instead, make sure Anaconda's bin directory is on your path.
Unless you have a very recent (1.10, currently in development) version of numpy, to use gfortran, you'll need to go to Anaconda/Lib/site-packages/numpy/distutils/fcompiler/gnu.py and comment out the lines (somewhere around line 330) that raise an error if you're on 64 bit windows.
Once you've done that, it should work fine.
Edit: judging by the old f2py docs and the current source, the proper fcompiler flag is --fcompiler=nag.
The compiler is specified by vendor, not by executable name.

Related

How to install C++ dependencies "from source" for a Python package on Mac OS?

There is a Github repo containing Python "bindings" for a C++ library that I am interested in playing with. The README has abundant information about how to install the C++ library on Linux like machines, but no information about how to do so with a mac OS.
I have also opened up an issue requesting the README installation instructions include mac OS-specific installs in addition to linux. There hasn't been any activity on that issue.
Here are the two repos:
(Python) https://github.com/asiffer/python3-libspot
(C++) https://github.com/asiffer/libspot
Since the C++ package isn't available for installing via Brew/pip/anaconda, I'm not sure how to get going.
What I've Tried:
I have tried ./configure, and make. There is no ./configure file.
To address the lack of ./configure, read about a tool called autoconf which supposedly generates ./configure for you. I installed it with brew, but am not sure what arguments to pass it. These docs were pretty hard to understand: https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Making-configure-Scripts.html
Just using make results in the error clang: error: unsupported option '-fopenmp'That sent me down a whole different rabbit hole which had me adding lines to the Makefile:
CPP = /usr/local/opt/llvm/bin/clang
CPPFLAGS = -I/usr/local/opt/llvm/include -fopenmp
LDFLAGS = -L/usr/local/opt/llvm/lib
omp_hello: omp_hello.c
$(CPP) $(CPPFLAGS) $^ -o $# $(LDFLAGS)
That felt dangerous because I have no idea what any of that stuff means. Plus it resulted in a new error: *** missing separator. Stop.
So then I read that's probably due to using "soft" tabs instead of "hard" tabs which can be identified using cat -e -t -v makefile_name. I found the one line where a "hard" tab was missing (the indented line above) and inserted it. This resulted in a new error:
make: *** No rule to make target `omp_hello.c', needed by `omp_hello'. Stop.
Next, following the advice of Yang Yushi and his follow on comments, I changed lines 39 and 40 according to his answer, plus added the locations of some additional files to the CXXFLAGS variable:
-I//opt/homebrew/Cellar/libomp/11.0.1/include
-L/opt/homebrew/Cellar/libomp/11.0.1/lib
And this got me a little further. Next, OSX didn't like where this script was trying to install, as explained by this answer. So I changed these two lines in the makefile which seemed to dictate install location:
INSTALL_HEAD_DIR = $(DESTDIR)/usr/include/libspot
INSTALL_LIB_DIR = $(DESTDIR)/usr/lib
to
INSTALL_HEAD_DIR = $(DESTDIR)/usr/local/include/libspot
INSTALL_LIB_DIR = $(DESTDIR)/usr/local/lib
And that indeed got me a little farther. Next I ran into an error complaining about the flat -t at these lines in the makefile:
#install -t $(INSTALL_LIB_DIR) $(LIB_DIR)/*.so
#install -t $(INSTALL_HEAD_DIR) $(INC_DIR)/*.h
So I deleted those flags, which then resulted in this error:
Checking the headers installation directory (/usr/local/include/libspot)
Checking the library installation directory (/usr/local/lib)
Installing the shared library (libspot.so)
install: /usr/local/lib: Inappropriate file type or format
For which I can find no reading material and have no clue how to fix. Any further assistance appreciated.
Here's a list of SO and other resources I've perused trying to answer this question:
Enable OpenMP support in clang in Mac OS X (sierra & Mojave)
makefile error: make: *** No rule to make target `omp.h' ; with OpenMP
makefile:4: *** missing separator. Stop
http://www.idryman.org/blog/2016/03/10/autoconf-tutorial-1/
https://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Making-configure-Scripts.html
https://developer.gnome.org/anjuta-build-tutorial/stable/create-autotools.html.en
My Question
How do I proceed.
If you know how to do this, could you also include a brief explanation of the concepts behind each step? I'd be happy to learn a little instead of just copying and pasting commands in the right order.
Compile the C++ source code with Apple Clang
I downloaded the prjoect (libspot) and successfully compiled it on my Mac. I change two lines (39 and 40) in the Makefile to make it work. (Following this answer)
CC = clang++ # change from g++ to default Apple clang
CXXFLAGS = -std=c++11 -Wall -pedantic -Xpreprocessor -fopenmp -lomp # additional flags
You should get the binary file by just type make with a "correct" Makefile.
(If you see something like "cant find omp.h", add -I/usr/local/opt/libomp/include to the CXXFLAGS.)
For the Question
The error message in the updated question description
make: *** No rule to make target omp_hello.c', needed by omp_hello'. Stop.
is telling us that the file omp_hello.c is missing. The Makefile is written to compile the source code omp_hello.c to an executable binary file omp_hello. If I have the C source file (omp_hello.c), the Makefile will allow me to compile by just typing
make
instead of
/usr/local/opt/llvm/bin/clang \
-I/usr/local/opt/llvm/include -fopenmp \
-L/usr/local/opt/llvm/lib \
omp_hello.c -o omp_hello
This is just a normal compile process, it has nothing to do with Python. The error message is saying the source code to be compiled (omp_hello.c) is missing.
It looks like this is a small project with custom Makefile. Normally you compile the code with just make. The error you got seems to suggest the lack of llvm. You may want to try install llvm following this answer.
Usually it comes to running brew install <your C++ package> or downloading the source code to some directory and running a set of commands:
./configure
make
make install
While usually it works, some packages can not be installed on Mac since their maintainers did not prepare configuration for Mac.

How to pass linker flags to f2py?

I am trying to wrap a set of Fortran files to Python using f2py. I am using the gfortran compiler via mingw64. The sources I am trying to wrap contain Lapack functions, so I built Lapack and Blas following the "Easy windows build" instructions on this webpage: https://icl.cs.utk.edu/lapack-for-windows/lapack/#build. I am now able to compile my source file by running
gfortran foo.F90 -ffree-line-length-512 -llapack -lblas -fdec-math -Wl,-allow-multiple-definition
As you can see I need to pass a set of options, which are not really all that relevant here except for the last one -Wl,-allow-multiple-definition. I have found that if I do not include this option the file won't compile and I get a whole set of errors all ending with multiple definition of `_gfortran[...] where [...] contains some extra string, like for example _st_open'. Perhaps that last option is a bit of a hack, but at least the file compiles without issues.
However I do not know how to pass this linker option to f2py. Currently I run,
python -m numpy.f2py -llapack -lblas -c foo.F90
--fcompiler=gnu95 --compiler=mingw32 --f90flags="-ffree-line-length-512 -fdec-math -Wl,-allow-multiple-definition" -m foo_py
But this doesn't seem to do anything, I just get the same multiple definition error as if the linker flag wasn't included. So what syntax should I use?
Thanks!
EDIT: After some extensive googling it seems like f2py contains no option to pass linker flags to the compiler. So now I am wondering if there is some way to force the allow-multiple-definition option on the compiler globally.
I think the error itself must somehow originate in how I have built LAPACK and BLAS. Similar errors have been reported before, see https://icl.cs.utk.edu/lapack-forum/viewtopic.php?f=4&t=5315, but seemingly only in the built process and not during a fortran compile. Would there be alternative ways to build LAPACK such that I can easily incorporate it with gfortran?
Did you have a look at this: how to tell f2py module to look in current directory for shared object dependency
There the following is suggested:
set env variable export LDFLAGS=-Wl,-rpath=.
set env variable export NPY_DISTUTILS_APPEND_FLAGS=1
upgrade numpy to 1.16.0 or greater

Py_Initialize undefined reference

I want to add python functions in C++ code.
I made a GUI in gtk (on the Raspberry PI) and now I want to work with a camera module which is easy to handle in python. (I want to start a video directly when I push a button.)
So I included the file Python.h
#include <python3.4m/Python.h>
#include <python3.4m/pythonrun.h>
then I thought it should work, but when I try to compile Py_Initialize()
I get the error:
undefined reference to Py_Initialize.
I think this is strange because, when I type in, there came the selection for Py_Initialize.
In terms of headers you should be fine, since it compiled but failed at linking.
Now you need to link against the Python libraries. The way this is done largely depends on what toolchain you are using.
Maybe you can see my answer in another question:
if with python 3.x installed, maybe this command can work:
g++ hw.cpp `/usr/bin/python3-config --cflags` `/usr/python3-config --ldflags`
By the way, you should check you gcc and python version.
As I know, if gcc version is 5.4 and python version is 3.7, it doesn't work.(python 3.5 >is work)
When you run /usr/bin/python3-config --cflags, in fact, it is the compile option.
Set the python include folder and it static lib on gcc command line and put the python dynamic lib on LD_LIBRARY_PATH. Before Py_Initialize(), do not forget to set python home with Py_SetPythonHome(). These steps must be sufficient for your code compile and run.

What does "Symbol not found / Expected in: flat namespace" actually mean?

When I import a module I built, I get this boost-python related error:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dlopen(./myMod.so, 2): Symbol not found: __ZN5boost6python7objects15function_objectERKNS1_11py_functionERKSt4pairIPKNS0_6detail7keywordES9_E
Referenced from: ./myMod.so
Expected in: flat namespace
in ./myMod.so
What does this actually mean? Why was this error raised?
Description
The problem was caused by mixing objects that compiled with libc++ and object that compiled with libstdc++.
In our case, the library myMod.so (compiled with libstdc++) need boost-python that compiled with libstdc++ (boost-python-libstdc++ from now). When boost-python is boost-python-libstdc++, it will work fine. Otherwise - on computer that its boost-python has compiled with libc++ (or another c++ library), it will have a problem loading and running it.
In our case, it happens because that libc++ developers intentionally changed the name of all of their symbols to prevent you (and save you) from mixing code from their library and code from a different one: myMod.so need a function that take an argument from the type. In libc++, this type's name is std::__1::pair. Therefore, this symbol was not found.
To understand why mixing two version of the same API is bad, consider this situation: There are two libraries: Foo and Bar. They both have a function that takes a std::string and uses it for something but they use a different c++ library. When a std::string that has been created by Foo will be passed to Bar, Bar will think that this is an instance of its c++ library's std::string and then bad things can happen (they are a completely different objects).
Note: In some cases, there would be no problem with two or more different versions of the same API in a completely different parts of a program. There will be a problem if they will pass this API's objects between them. However, checking that can be very hard, especially if they pass the API object only as a member of another object. Also, a library's initialization function can do things that should not happen twice. Another version may do these things again.
How to solve that?
You can always recompile your libraries and make them match each other.
You can link boost-python to your library as a static library. Then, it will work on almost every computer (even one that doesn't has boost-python installed). See more about that here.
Summary
myMod.so need another version of boost-python, one that compiled with a specific c++ library. Therefore, It would not work with any another version.
In my case I was receiving:
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/xmlsec.cpython-38-darwin.so, 0x0002): symbol not found in flat namespace '_xmlSecDSigNs'
BACKGROUND:
M1 MacBook Pro with Montery
I was working with a python virtualenv (using pyenv) to use an earlier version of python3.8 (3.8.2), while my system had 3.8.10 installed natively.
While I was in the activated 3.8.2 virtualenv I noticed the path in dlopen() was pointing to the package in the native python install NOT the virtualenv install.
SOLUTION:
In my case, I did not need the native 3.8 version at all so I simply removed it and this solved the problem.
I encounter the same problem.
Expected in: flat namespace
Add the linker flag fixes the problem
-lboost_python37
change the dynamic library name to the one installed on the os.
By the way, my os is macOS High Sierra and I use brew to install boost_python3.
Symbol not found means the definition of the declared function or variable was not found. When a header file of a shared object is compiled with your program, linker adds symbols of declared functions and objects to your compiled program. When your program is loaded by the OS's loader, the symbols are resolved so that their definition will be loaded. It is only at this time where if the implementation is missing, loader complains it couldn't find the definition due to may be failing to resolve the actual path to the library or the library itself wasn't compiled with the implementation/source file where the definition of the function or object resides. There is a good article on this on the linux journal http://www.linuxjournal.com/article/6463.
In my case I was just failing to import all the required sources (c++ files) when compiling with Cython.
From the string after "Symbol not found" you can understand which library you are missing.
One of the solutions I found was to uninstall and reinstall it using the no-binary flag, which forces pip to compile the module from source instead of installing from precompiled wheel.
pip install --no-binary :all: <name-of-module>
Found this solution here
Here's what I've learned (osx):
If this is supposed to work (i.e. it works on another computer), you may be experiencing clang/gcc issues. To debug this, use otool -l on the .so file which is raising the error, or a suspect library (in my example it's a boost-python dylib file) and examine the contents. Anything in the /System/ folder is built with clang, and should be installed somewhere else with the gcc compiler. Never delete anything in the /System folder.
.so files are dynamic libraries (so = shared object). On Windows they are called .dll (dynamic-link library). They contain compiled code which contains functions available for usage to any executable which links them.
What is important to notice here is that those .so are not Python files. They were probably compiled from C or C++ code and contain public functions which can be used from Python code (see documentation on Extending Python with C or C++).
On your case, well, you have a corrupt .so. Try reinstalling the affected libraries, or Python, or both.
Problem
I had this same issue when running puma as part of Rails app
LoadError:
dlopen(/Users/alucard/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/puma-5.6.4/lib/puma/puma_http11.bundle, 0x0009): symbol not found in flat namespace '_ERR_load_crypto_strings'
/Users/alucard/.rbenv/versions/2.7.6/lib/ruby/gems/2.7.0/gems/puma-5.6.4/lib/puma/puma_http11.bundle
Solution
It was solved just by installing puma gem again gem install puma

Python failing to compile on Linux with custom module built in

I am trying to compile Python 2.6.7 with a custom module built in but I am running into problems. Everything is going fine until the linker tries to link the dependencies that my module has. The make file gets generated just fine and the path were the libraries are installed to is correct. The way I configured Python to compile with my custom module is like so:
_myplugin _myplugin.c++ -I/home/me/Desktop/Depends/include -L/home/me/Desktop/Depends/lib -l libcrvs_pic.a -l libsb_pic.a -l liblmgr_dongle_stup_pic.a
The build fails on this line:
/usr/bin/ld: cannot find -llibcrvs_pic.a
Any help would be much appreciated!
I think what you need to do is specify the libraries without the lib prefix, and also without the .a suffix.
Like so:
-lcrvs_pic

Categories