Compile PyTorch with additional linker options - python

I have a modified version of the gloo library. I am able to compile and run programs that use this library (similar to what you can find in gloo/gloo/examples).
Now, I want to build pytorch with my library.
I replaced the third_party/gloo folder in PyTorch with my version of gloo and I am trying to compile it.
However, my version of gloo requires some additional libraries and special linker options. Where should these linker options be added in the pytorch build system?
Without these linker options, my compilation stops with the linker error:
/pytorch/build/lib/libcaffe2_gpu.so: undefined reference to <my code>
/pytorch/build/lib/libcaffe2.so: undefined reference to <my code>

The additional linker options should be added to:
the Caffe2_DEPENDENCY_LIBS variable in pytorch/caffe2/CMakeLists.txt with the command:
list(APPEND Caffe2_DEPENDENCY_LIBS <linker_options>)
the C10D_LIBS variable in pytorch/torch/lib/c10d/CMakeLists.txt with the command:
list(APPEND C10D_LIBS <linker_options>)
The additional libraries should have Position Independent Code (they must be compiled with the -fPIC flag).

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

Which version of `gcc` supports the `--no-undefined` switch?

I am trying to compile pynifti package from source (long story involving Anaconda Python distribution).
After running make, I receive the following error:
gcc: error: unrecognized command line option ‘--Wl,--no-undefined’
Indeed, the manual (man gcc) contains no information about --no-undefined switch. My version of gcc is 4.8.5. Also, I can not find the no-undefined option in https://gcc.gnu.org/onlinedocs/gcc/Option-Index.html#Option-Index
However, from Force GCC to notify about undefined references in shared libraries I infer that it is a valid switch at least for some version of gcc.
This switch is a linker option for ld. It is not directly part of GCC but it is only encapsulated in a -Wl option to be passed to the linker (you seem to have --Wl which is wrong).
Edit:
Yugr deserves part of the credit as he pointed out the incorrect --Wl option!

python c++ extension: symbol not defined error

I have a working c++ code that I want to wrap into a python module on Windows XP and Python 2.7. I have never done this before, so I looked into swig and distutils.
I created an interface file and a setup.py and compiled using
python setup.py build_ext -c mingw32
The script creates a module_wrap.cpp from my module.i and module.cpp file, and then creates a module_wrap.o and a module.o. The creation of module.o creates a bunch of Warnings for unused variables and deprecated char*, but it seems to work. Because the C++-code is not mine, I don't really want to get into these right now.
The last step is executing
g++.exe -shared -s build\temp.win32-2.7\Release\module_wrap.o build\temp.win32-2.7\Release\module.o build\temp.win32-2.7\Release\_module.def -LC:\Programme\Python27\libs -LC:\Programme\Python27\PCbuild -lpython27 -o build\lib.win32-2.7\_module.pyd
I get
Cannot export init_module: symbol not defined
error: command 'g++' failed with exit status 1
I googled a lot to this now, and I just can not find a solution to this problem. The previously created _module.def seems to try to export this init since it contains
LIBRARY _module.pyd
EXPORTS
init_module
Obviously this doesn't work, but I have no idea why. Can anyone help me out here?
I figured it out. The problem was the (not posted) interface file module.i for swig. There I named the module %module usemodule, whereas in the setup.py i named the module name=module. This way swig created an init_function, that did not match the name the created module was expecting it. In the end: just a typo...
Thanks for your support nevertheless!

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