Compliing C++ CGAL Module that is callable from Python - c++

I am trying to compile some C++ code that is to be called from Python and then calls CGAL.
I need to be able to specify some flags on compilation, but not sure how to do this as the build process is
./CGAL-4.2/scripts/cgal_create_CMakeLists -s CallGCAL
cmake -DCGAL_DIR=./CGAL-4.2 .
make
And I don't want to have to hand edit the Makefile or CMakeLists
The error message I get from above without Flags to tell gcc it need Python are
CMakeFiles/CallGCAL.dir/CallGCAL.cpp.o: In function `initmyModule()':
CallGCAL.cpp:(.text+0x5e): undefined reference to `Py_InitModule4'
CMakeFiles/CallGCAL.dir/CallGCAL.cpp.o: In function `py_polygon(_object*, _object*)':
CallGCAL.cpp:(.text+0x86): undefined reference to `Py_BuildValue'
CMakeFiles/CallGCAL.dir/CallGCAL.cpp.o: In function `py_hull(_object*, _object*)':
CallGCAL.cpp:(.text+0xa6): undefined reference to `Py_BuildValue'
collect2: ld returned 1 exit status

Okay solved!!! Had to pass a variable to cmake.
Working script is as follows.
./CGAL-4.2/scripts/cgal_create_CMakeLists -s CallCGAL
cmake -DCGAL_DIR=./CGAL-4.2 -DCGAL_CXX_FLAGS="-shared -fPIC" .
make
rm -f CallCGAL.so
mv CallCGAL CallCGAL.so

Do I understand you correctly that want to compile your own code, which uses both Python and CGAL, with the aid of a makefile that comes with CGAL?
That is obviously impossible, since the CGAL makefile cannot know about Python. You must write your own makefile, which can be based on some existing makefiles, but also knows about Phython. The error you're reporting is generated by the loader which cannot find the Python library to resolve certain symbols. Thus, all you have to add to the makefile are the relevant -l and -L options.

The CMakeLists.txt created by cgal_create_CMakeLists is not at all designed for your use case. The created CMakeLists.txt tries to compile an executable, whereas you want to create a module. In the CMakeLists.txt, replace the line:
create_single_source_cgal_program(CallCGAL.cpp)
by:
add_library(CallCGAL MODULE CallCGAL.cpp)
target_link_libraries(CallCGAL ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} )
That way, CMake will create the correct Makefile, without any need to rename a file, or tweak the compilation and linking flags.

Related

Undefined reference to 'event_base_del_virtual' when compiling libfluid sample controller

I'm trying to use libfluid to code my own OpenFlow controller. But first I want to build the sample controller to understand how that works.
I got the following error when compiling the sample controller:(this is the error I got when I try make msg_controller)
c++ msg/MsgController.cc -lfluid_msg -lfluid_base -I. -O3 -std=c++0x -o msg_controller
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libfluid_base.so: undefined reference to `event_base_del_virtual'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../../lib/libfluid_base.so: undefined reference to `event_base_add_virtual'
collect2: error: ld returned 1 exit status
Makefile:10: recipe for target 'msg_controller' failed
make: *** [msg_controller] Error 1
Before building sample controller, I follow the steps to build libfluid_base and libfluid_msg. When building these two library I got the following prompt which I think might be helpful to solve my problem
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
during execution
add LIBDIR to the 'LD_RUN_PATH' environment variable
during linking
use the '-Wl,-rpath -Wl,LIBDIR' linker flag
have your system administrator add LIBDIR to '/etc/ld.so.conf'
See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
Is the undefined reference error because the library not linking correctly?
Do I need to make some change to the c++ command?
I tried the command grep -rn "event_base_del" /usr/lib and also grep -rn "event_base_add" /usr/lib
The output for event_base_del is below (the same for event_base_add)
Binary file /usr/lib/libfluid_base.a matches
Binary file /usr/lib/libfluid_base.so.0.0.0 matches
Binary file /usr/lib/x86_64-linux-gnu/libevent.a matches
Binary file /usr/lib/x86_64-linux-gnu/libevent-2.1.so.6.0.2 matches
Binary file /usr/lib/x86_64-linux-gnu/libevent_core.a matches
Binary file /usr/lib/x86_64-linux-gnu/libevent_core-2.1.so.6.0.2 matches
Is this means it is linking correctly? since libfluid_base.so is just a link to libfluid_base.so.0.0.0
lrwxrwxrwx 1 root root 22 Oct 8 09:36 libfluid_base.so -> libfluid_base.so.0.0.0
So how can I fix this?
After I tried using -levent_core or -levnet to have the example code link against libevent. The error continue exist, it's probably because the version of libevent I'm using right now is not compatible with the current version of libfluid.By the way I'm using Ubuntu18.04.
I will try build it on ubuntu16.04 with older version of libevent see if it works.
event_base_del_virtual comes from libevent library. Link it with -levent_core.

METIS: undefined reference to `METIS_WPartGraphRecursive'

I have to compile a software that depends on METIS library, but whose CMake thing was written by disabling all the places where METIS was needed. Now, I have to re-enable that code again and thus the code depends now on METIS.
I installed metis-5.1.0 from source, and I wrote a CMake module to find it (actually I used this one). I modify the CMakeLists.txt accordingly, basically adding the following lines
find_package(METIS REQUIRED)
if (METIS_FOUND)
include_directories(SYSTEM ${METIS_INCLUDE_PATH})
else (METIS_FOUND)
message (SEND_ERROR "This application cannot compile without METIS")
endif (METIS_FOUND)
and, at the end,
target_link_libraries(<my_executable> ${METIS_LIBRARIES})
After cmake, it seems everything is fine, because cmake prints:
-- Found METIS: /usr/local/include
-- METIS libraries /usr/local/lib/libmetis.a
...
-- Configuring done
-- Generating done
-- Build files have been written to: <mylocation>
However, after I run make, I get
undefined reference to `METIS_WPartGraphKway'
undefined reference to `METIS_WPartGraphRecursive'
How can I solve?
EDIT:
As an additional information, when I compile with make VERBOSE=1, the linker seems to look for the right library, as it includes /usr/local/lib/libmetis.a, which corresponds to the location that cmake was specifying and which also exists. Moreover, when I look into the library with nm /usr/local/lib/libmetis.a, I see:
00000000000001c0 T METIS_WPartGraphKway
00000000000009c0 T METIS_WPartGraphRecursive
P.S.: In Ubuntu 17.04, I have tried with metis-5.1.0, metis-4.0.3 and also installing with sudo apt-get install libmetis-dev. In the latter case I find libmetis.so instead of libmetis.a, but, also in this case, this is correctly recognized by cmake, correctly looked for by the linker, but at the end I get the same error.
I also tried sudo apt-get install libmetis-dev, installing from source metis-5.1.0 and metis-3.0.6 on Ubuntu 14.04 and I had the same problem.
This seems a hard-to-solve error, as many people ask the same question in this page of the METIS formum.
I have also tried to add -lmetis at the end of the compilation command, as suggested here
As an additional information, I did a grep WPartGraphKway in the METIS source folder. In version 5.1.0 there is no such string. In version 4.0.3 there is.
I solved doing this:
I install metis-3.0
I run cmake for my software
I run make VERBOSE=1
I copy the last gcc command being printed
I paste it, I add at the end of the command -lmetis and execute the command
Note that, if I repeat the same operation with metis-5.1.0, it does not work and I have the same error that I wrote in the first post.

usr/bin/ld: cannot find -l<nameOfTheLibrary>

I'm trying to compile my program and it returns this error :
usr/bin/ld: cannot find -l<nameOfTheLibrary>
in my makefile I use the command g++ and link to my library which is a symbolic link to my library located on an other directory.
Is there an option to add to make it work please?
To figure out what the linker is looking for, run it in verbose mode.
For example, I encountered this issue while trying to compile MySQL with ZLIB support. I was receiving an error like this during compilation:
/usr/bin/ld: cannot find -lzlib
I did some Googl'ing and kept coming across different issues of the same kind where people would say to make sure the .so file actually exists and if it doesn't, then create a symlink to the versioned file, for example, zlib.so.1.2.8. But, when I checked, zlib.so DID exist. So, I thought, surely that couldn't be the problem.
I came across another post on the Internets that suggested to run make with LD_DEBUG=all:
LD_DEBUG=all make
Although I got a TON of debugging output, it wasn't actually helpful. It added more confusion than anything else. So, I was about to give up.
Then, I had an epiphany. I thought to actually check the help text for the ld command:
ld --help
From that, I figured out how to run ld in verbose mode (imagine that):
ld -lzlib --verbose
This is the output I got:
==================================================
attempt to open /usr/x86_64-linux-gnu/lib64/libzlib.so failed
attempt to open /usr/x86_64-linux-gnu/lib64/libzlib.a failed
attempt to open /usr/local/lib64/libzlib.so failed
attempt to open /usr/local/lib64/libzlib.a failed
attempt to open /lib64/libzlib.so failed
attempt to open /lib64/libzlib.a failed
attempt to open /usr/lib64/libzlib.so failed
attempt to open /usr/lib64/libzlib.a failed
attempt to open /usr/x86_64-linux-gnu/lib/libzlib.so failed
attempt to open /usr/x86_64-linux-gnu/lib/libzlib.a failed
attempt to open /usr/local/lib/libzlib.so failed
attempt to open /usr/local/lib/libzlib.a failed
attempt to open /lib/libzlib.so failed
attempt to open /lib/libzlib.a failed
attempt to open /usr/lib/libzlib.so failed
attempt to open /usr/lib/libzlib.a failed
/usr/bin/ld.bfd.real: cannot find -lzlib
Ding, ding, ding...
So, to finally fix it so I could compile MySQL with my own version of ZLIB (rather than the bundled version):
sudo ln -s /usr/lib/libz.so.1.2.8 /usr/lib/libzlib.so
Voila!
If your library name is say libxyz.so and it is located on path say:
/home/user/myDir
then to link it to your program:
g++ -L/home/user/myDir -lxyz myprog.cpp -o myprog
There does not seem to be any answer which addresses the very common beginner problem of failing to install the required library in the first place.
On Debianish platforms, if libfoo is missing, you can frequently install it with something like
apt-get install libfoo-dev
The -dev version of the package is required for development work, even trivial development work such as compiling source code to link to the library.
The package name will sometimes require some decorations (libfoo0-dev? foo-dev without the lib prefix? etc), or you can simply use your distro's package search to find out precisely which packages provide a particular file.
(If there is more than one, you will need to find out what their differences are. Picking the coolest or the most popular is a common shortcut, but not an acceptable procedure for any serious development work.)
For other architectures (most notably RPM) similar procedures apply, though the details will be different.
Compile Time
When g++ says cannot find -l<nameOfTheLibrary>, it means that g++ looked for the file lib{nameOfTheLibrary}.so, but it couldn't find it in the shared library search path, which by default points to /usr/lib and /usr/local/lib and somewhere else maybe.
To resolve this problem, you should either provide the library file (lib{nameOfTheLibrary}.so) in those search paths or use -L command option. -L{path} tells the g++ (actually ld) to find library files in path {path} in addition to default paths.
Example: Assuming you have a library at /home/taylor/libswift.so, and you want to link your app to this library. In this case you should supply the g++ with the following options:
g++ main.cpp -o main -L/home/taylor -lswift
Note 1: -l option gets the library name without lib and .so at its beginning and end.
Note 2: In some cases, the library file name is followed by its version, for instance libswift.so.1.2. In these cases, g++ also cannot find the library file. A simple workaround to fix this is creating a symbolic link to libswift.so.1.2 called libswift.so.
Runtime
When you link your app to a shared library, it's required that library stays available whenever you run the app. In runtime your app (actually dynamic linker) looks for its libraries in LD_LIBRARY_PATH. It's an environment variable which stores a list of paths.
Example: In case of our libswift.so example, dynamic linker cannot find libswift.so in LD_LIBRARY_PATH (which points to default search paths). To fix the problem you should append that variable with the path libswift.so is in.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/taylor
During compilation with g++ via make define LIBRARY_PATH if it may not be appropriate to change the Makefile with the -Loption. I had put my extra library in /opt/lib so I did:
$ export LIBRARY_PATH=/opt/lib/
and then ran make for successful compilation and linking.
To run the program with a shared library define:
$ export LD_LIBRARY_PATH=/opt/lib/
before executing the program.
First, you need to know the naming rule of lxxx:
/usr/bin/ld: cannot find -lc
/usr/bin/ld: cannot find -lltdl
/usr/bin/ld: cannot find -lXtst
lc means libc.so, lltdl means libltdl.so, lXtst means libXts.so.
So, it is lib + lib-name + .so
Once we know the name, we can use locate to find the path of this lxxx.so file.
$ locate libiconv.so
/home/user/anaconda3/lib/libiconv.so # <-- right here
/home/user/anaconda3/lib/libiconv.so.2
/home/user/anaconda3/lib/libiconv.so.2.5.1
/home/user/anaconda3/lib/preloadable_libiconv.so
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so.2
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/libiconv.so.2.5.1
/home/user/anaconda3/pkgs/libiconv-1.14-0/lib/preloadable_libiconv.so
If you cannot find it, you need to install it by yum (I use CentOS). Usually you have this file, but it does not link to right place.
Link it to the right place, usually it is /lib64 or /usr/lib64
$ sudo ln -s /home/user/anaconda3/lib/libiconv.so /usr/lib64/
Done!
ref: https://i-pogo.blogspot.jp/2010/01/usrbinld-cannot-find-lxxx.html
When you compile your program you must supply the path to the library; in g++ use the -L option:
g++ myprogram.cc -o myprogram -lmylib -L/path/foo/bar
I had this problem with compiling LXC on a fresh VM with Centos 7.8. I tried all the above and failed. Some suggested removing the -static flag from the compiler configuration but I didn't want to change anything.
The only thing that helped was to install glibc-static and retry. Hope that helps someone.
Check the location of your library, for example lxxx.so:
locate lxxx.so
If it is not in the /usr/lib folder, type this:
sudo cp yourpath/lxxx.so /usr/lib
Done.
Apart from the answers already given, it may also be the case that the *.so file exists but is not named properly. Or it may be the case that *.so file exists but it is owned by another user / root.
Issue 1: Improper name
If you are linking the file as -l<nameOfLibrary>
then library file name MUST be of the form lib<nameOfLibrary>
If you only have <nameOfLibrary>.so file, rename it!
Issue 2: Wrong owner
To verify that this is not the problem - do
ls -l /path/to/.so/file
If the file is owned by root or another user, you need to do
sudo chown yourUserName:yourUserName /path/to/.so/file
Here is Ubuntu information of my laptop.
lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.2 LTS
Release: 18.04
Codename: bionic
I use locate to find the .so files for boost_filesystem and boost_system
locate libboost_filesystem
locate libboost_system
Then link .so files to /usr/lib and rename to .so
sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.65.1 /usr/lib/libboost_filesystem.so
sudo ln -s /usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1 /usr/lib/libboost_system.so
Done! R package velocyto.R was successfully installed!
This error may also be brought about if the symbolic link is to a dynamic library, .so, but for legacy reasons -static appears among the link flags. If so, try removing it.
The library I was trying to link to turned out to have a non-standard name (i.e. wasn't prefixed with 'lib'), so they recommended using a command like this to compile it -
gcc test.c -Iinclude lib/cspice.a -lm
I encountered the same error message.
I built the cmocka as a so and tried to link it to my executable.
But ld always complains below:
/usr/bin/ld: cannot find -lcmocka
It turns out that there are 3 files generated after cmocka is built:
libcmocka.so
libcmocka.so.0
libcmocka.so.0.7.0
1 and 2 are symbol links and only 3 is the real file.
I only copied the 1 to my library folder, where ld failed to find the 3.
After I copied all 3, ld works.

Errors when linking a custom Apache 2.4 modules statically with httpd/apr libraries on Linux

I am attempting to move my module to Linux Apache 2.4 and I am having linking issues. On windows a libhttpd.lib is available to link against as well as the apr/apr-util libraries. lib* httpd apr and aprutil are all statically linked on my windows installation. I want to do the same for the Linux installation.
According to the limited documentation available I am unable to use APXS because my module is written in C++.
I am having difficulties finding the archive files for the server on Linux. What do I need to link against for my module to work?
The source is able to link and execute on a Windows host.
Sample errors:
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:367: undefined reference to `pthread_mutexattr_init'
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:374: undefined reference to `pthread_mutexattr_setpshared'
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:384: undefined reference to `pthread_mutexattr_setrobust_np'
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:393: undefined reference to `pthread_mutexattr_setprotocol'
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:414: undefined reference to `pthread_mutexattr_destroy'
/home/ec2-user/httpd-2.4.2/srclib/apr/locks/unix/proc_mutex.c:408: undefined reference to `pthread_mutexattr_destroy'
Thanks
These errors means you didn't add -pthread to your compile command line, so you're not getting the pthread library linked in.
(Note: it's -pthread, not -lpthread - it's not just a linker option.)
For those building Apache modules in C++ and want dynamic linking, here's the g++ command line I used to successfully build a module; briefly tested on Apache 2.2.22/CentOS 6.2.
g++ [my files].cpp -I/httpd/include/ -I/httpd/srclib/apr/include/
-I/httpd/srclib/apr-util/include/ -I/usr/include/ -I/usr/include/apr-1/
-I/httpd/os/unix/ -shared -fPIC -o mod_mymodule.so
I'm an Apache/linux programming noob and was unable to find this info anywhere else; thanks to the OP's solution I was able to finish the job after a few days of frustration.
Here's also a link which helped explain how to work around the 'unresolved reference' linker issue when it couldn't find the apache functions contained within the httpd server core code (libhttpd.lib on Windows) -- which doesn't exist in *nix, unless you make it manually like the OP did. Basically, the answer was to use the -shared flag so these references are automagically resolved at run time.
http://www.yolinux.com/TUTORIALS/LibraryArchives-StaticAndDynamic.html
Don't forget the 'extern C' in your module code, and build in DSO support when building HTTPD.
Hope this helps someone else!
So anyone else searching for this may get the answer.
Download whatever Apache version (higher than 2.2) source from the apache httpd site to the home directory
Unpack
Configure with everything or simply just specify no options (You can
reconfigure later for the actual build)
perform a make on the source ( don't do a make install yet! just need the object files)
create a directory that will hold your libraries and source for your
own module. Say "foo" at the top level of your home dir (or any you
desire)
assuming home dir: execute (find ~/httpdX.X -name '*.o' -exec cp {} ~/foo \;) The command is in parenthesis. This will copy all compiled objects to foo.
execute (find ~/foo -name '*.o' -exec ar r libhttpd.a {} \;) which
will create an archive of the code for you.
Then just include these switches in your compile definition for gcc
or g++ (-Wl,-Bstatic -lhttpd -lpcre -lpcreposix -lapr-1 -laprutil-1
-Wl,-Bdynamic -pthread -ldl -lcrypt)
Clean up your foo directory if you like by running rm on the *.o
files
You do not need to compile statically like I needed to, but I wanted to be able to move my module to any Linux host without worry about the necessary components. Apache needs pcre(regex), apr(all libraries), threads (proc/thread mutex), dl(dynamic loading), and crypt(apr password) to work. Since thread, dl, and crypt will most like already be on the machine, I chose to not compile them statically.
Happy hunting. I hope my never ending story over 3 days helps someone else!

Making autoconf search for C++ libraries

I'm writing my first configure.ac and need to search for a C++ library.
I tried the following line, but when run the configure script, it finds nothing.
AC_SEARCH_LIBS([xmlpp::Document::get_root_node], [xml++-2.6])
Probably something is wrong with it. So, how can I make autoconf look for C++ libraries? I don't want to supply a global method (and don't think libxml++ has one either).
You might want to try AX_CXX_CHECK_LIB from the Autoconf macro archive. you should probably make sure that you either use AC_LANG([C++]) or surround the call with AC_LANG_PUSH([C++]) and AC_LANG_POP([C++]).
This link is about finding a C-style signature function to the library so that it can be tested by autoconf or write your own test:
https://nerdland.net/2009/07/detecting-c-libraries-with-autotools/
Maybe worth to try, but I am getting an error with the AC_LANG_PROGRAM macro. The problem is put -llibname before the foo.cpp file. My compiler cares about the order of the -l and cpp file. The linker will not be able to find the function in the library.
Hope this helps. My suggestion would be to use CMake instead of Autoconf.
This CMakeLists.txt file should get you started:
cmake_minimum_required(VERSION 2.8)
# http://www.cmake.org/cmake/help/cmake-2-8-docs.html#module:FindLibXml2
find_package(libxml2 2.6 REQUIRED) # http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:find_package
include_directories(${LIBXML2_INCLUDE_DIR}) # http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:include_directories
add_executable(myApp main.cpp other.cpp) # http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_executable
target_link_libraries(myApp ${LIBXML2_LIBRARIES}) # http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:target_link_libraries
To use the file, after adjusting for your project of course. Put it in your Source dir as CMakeLists.txt, then:
mkdir build
cd build
cmake .. # This is like autoconf and generates the make files
make
If it sounds intriguing check out the giant youtube vid on all the benefits: http://www.youtube.com/watch?v=8Ut9o4OdSC0
It's good to use CMake, CTest, CDash, and CPack together in a project.