Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compile error] Linker errors when building static libs with PCL_BUIILD_SHARED=OFF #4377

Open
themightyoarfish opened this issue Sep 2, 2020 · 8 comments
Labels
kind: compile error Type of issue module: cmake needs: testing Specify why not closed/merged yet platform: linux skill: cmake Skills/areas of expertise needed to tackle the issue

Comments

@themightyoarfish
Copy link
Contributor

themightyoarfish commented Sep 2, 2020

Describe the error

Compilation of 1.11.0 fails when build configured with cmake .. -DPCL_SHARED_LIBS=OFF -DWITH_OPENGL=OFF -DCMAKE_VERBOSE_MAKEFILE=1.

The errors are of the form

/usr/lib/x86_64-linux-gnu/libpthread.a(ptw-write.o): In function `__write_nocancel':
/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: undefined reference to `__syscall_error'
/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: undefined reference to `__syscall_error'
/usr/lib/x86_64-linux-gnu/libpthread.a(ptw-read.o): In function `__read_nocancel':
/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: undefined reference to `__syscall_error'
/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: undefined reference to `__syscall_error'
/usr/lib/x86_64-linux-gnu/libpthread.a(ptw-close.o): In function `__close_nocancel':
/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: undefined reference to `__syscall_error'
/usr/lib/x86_64-linux-gnu/libpthread.a(ptw-close.o):/build/glibc-e6zv40/glibc-2.23/nptl/../sysdeps/unix/syscall-template.S:84: more undefined references to `__syscall_error' follow

and occur for some compilation units, but others build fine. One affected target is pcl_pcd_introduce_nan.

To Reproduce

  • be on Ubuntu 16.04 (bare-bones docker container)
  • download 1.11.0 release
  • cmake .. -DPCL_SHARED_LIBS=OFF -DWITH_OPENGL=OFF -DCMAKE_VERBOSE_MAKEFILE=1
  • make -j8

Screenshots/Code snippets/Build information
The cmake output is this

cmake .. -DPCL_SHARED_LIBS=OFF -DWITH_OPENGL=OFF -DCMAKE_VERBOSE_MAKEFILE=1 -DCMAKE_BUILD_TYPE=Debug
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.1")
-- Could NOT find ClangFormat (missing: ClangFormat_EXECUTABLE ClangFormat_VERSION) (Required is at least version "10")
-- Performing Test HAVE_MARCH
-- Performing Test HAVE_MARCH - Success
-- Using CPU native flags for SSE optimization: -march=native
-- Performing Test HAVE_MM_MALLOC
-- Performing Test HAVE_MM_MALLOC - Success
-- Performing Test HAVE_POSIX_MEMALIGN
-- Performing Test HAVE_POSIX_MEMALIGN - Success
-- Performing Test HAVE_SSE4_2_EXTENSIONS
-- Performing Test HAVE_SSE4_2_EXTENSIONS - Success
-- Performing Test HAVE_SSE4_1_EXTENSIONS
-- Performing Test HAVE_SSE4_1_EXTENSIONS - Success
-- Performing Test HAVE_SSSE3_EXTENSIONS
-- Performing Test HAVE_SSSE3_EXTENSIONS - Success
-- Performing Test HAVE_SSE3_EXTENSIONS
-- Performing Test HAVE_SSE3_EXTENSIONS - Success
-- Performing Test HAVE_SSE2_EXTENSIONS
-- Performing Test HAVE_SSE2_EXTENSIONS - Success
-- Performing Test HAVE_SSE_EXTENSIONS
-- Performing Test HAVE_SSE_EXTENSIONS - Success
-- Found OpenMP_C: -fopenmp (found version "4.0")
-- Found OpenMP_CXX: -fopenmp (found version "4.0")
-- Found OpenMP: TRUE (found version "4.0") found components:  C CXX
-- Found OpenMP, spec date 201307
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Checking for module 'eigen3'
--   Found eigen3, version 3.2.92
-- Found Eigen: /usr/include/eigen3 (Required is at least version "3.1")
-- Eigen found (include: /usr/include/eigen3, version: 3.2.92)
-- Checking for module 'flann>=1.7.0'
--   Found flann, version 1.8.4
-- Found FLANN: /usr/lib/x86_64-linux-gnu/libflann_cpp_s.a (Required is at least version "1.7.0")
-- Could NOT find LIBUSB_1 (missing: LIBUSB_1_LIBRARY LIBUSB_1_INCLUDE_DIR)
-- Checking for module 'libusb-1.0'
--   No package 'libusb-1.0' found
-- Could NOT find USB_10 (missing: USB_10_LIBRARY USB_10_INCLUDE_DIR)
-- OpenNI disabled because libusb-1.0 not found.
-- OpenNI grabber support: not building because OpenNI not found
-- Checking for module 'libusb-1.0'
--   No package 'libusb-1.0' found
-- Could NOT find USB_10 (missing: USB_10_LIBRARY USB_10_INCLUDE_DIR)
-- OpenNI 2 disabled because libusb-1.0 not found.
-- OpenNI2 grabber support: not building because OpenNI2 not found
-- Could NOT find ENSENSO (missing: ENSENSO_LIBRARIES ENSENSO_INCLUDE_DIRS)
-- IDS-Imaging Ensenso camera support: not building because Ensenso not found
-- Could NOT find davidSDK (missing: DAVIDSDK_LIBRARY DAVIDSDK_INCLUDE_DIR)
-- David Vision Systems SDK support: not building because davidSDK not found
-- Could NOT find DSSDK (missing: DSSDK_LIBRARIES DSSDK_INCLUDE_DIRS)
-- DepthSense SDK support: not building because DSSDK not found
-- Could NOT find RSSDK (missing: RSSDK_LIBRARIES RSSDK_INCLUDE_DIRS)
-- RealSense SDK support: not building because RSSDK not found
-- Could NOT find RSSDK2
-- RealSense SDK 2.0 (librealsense) support: not building because RSSDK2 not found
-- Checking for module 'metslib'
--   No package 'metslib' found
-- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.a (found version "1.2.8")
-- Found PNG: /usr/lib/x86_64-linux-gnu/libpng.a (found version "1.2.54")
-- Could NOT find Qhull (missing: QHULL_LIBRARIES QHULL_INCLUDE_DIRS)
-- The imported target "vtkRenderingPythonTkWidgets" references the file
   "/usr/lib/x86_64-linux-gnu/libvtkRenderingPythonTkWidgets.so"
but this file does not exist.  Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
   "/usr/lib/cmake/vtk-6.2/VTKTargets.cmake"
but not all the files it references.

-- The imported target "vtk" references the file
   "/usr/bin/vtk"
but this file does not exist.  Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
   "/usr/lib/cmake/vtk-6.2/VTKTargets.cmake"
but not all the files it references.

-- VTK_MAJOR_VERSION 6, rendering backend: OpenGL
Warning: You are to build PCL in STATIC but VTK is SHARED!
Warning: VTK disabled!
-- Found PCAP: /usr/lib/x86_64-linux-gnu/libpcap.a
-- Found Boost: /usr/include (found suitable version "1.58.0", minimum required is "1.55.0") found components:  filesystem date_time iostreams system regex
-- Could NOT find OpenGL (missing: OPENGL_opengl_LIBRARY OPENGL_glx_LIBRARY)
-- Could NOT find GLEW (missing: GLEW_INCLUDE_DIRS GLEW_LIBRARIES)
-- DOXYGEN_FOUND
-- HTML_HELP_COMPILER
-- Found CPack generators: DEB
-- The following subsystems will be built:
--   common
--   kdtree
--   octree
--   search
--   sample_consensus
--   filters
--   2d
--   geometry
--   io
--   features
--   ml
--   segmentation
--   surface
--   registration
--   keypoints
--   tracking
--   recognition
--   stereo
--   tools
-- The following subsystems will not be built:
--   visualization: VTK was not found.
--   apps: Disabled by default
--   outofcore: Disabled manually.
--   examples: Code examples are disabled by default.
--   people: Disabled manually.
--   simulation: Disabled by default.
--   global_tests: Disabled by default
-- Configuring done
-- Generating done

Your Environment (please complete the following information):

  • OS: Ubuntu 16.04
  • Compiler: GCC 5.4.0
  • PCL Version:1.11.0
  • PCL Type: Compiled from source

If PCL was compiled from source or failure in compiling PCL itself:

  • GPU, Kinfu, CUDA enabled? No
  • List and Version of dependencies used: See cmake output above
  • Compilation flags are used: See cmake args above

Possible Solution

Some googling suggested this may be due to the fact that libc is not linked statically, maybe some flags like -static-libgcc or -static-libstdc++ are missing? Then again from what I read, one should not attempt to statically link libgcc. However this means the option to build static libpcl appears not to work in this configuration. It seems though that when I add -static -static-libstdc++ -static-libgcc to CMAKE_CXX_COMPILE_FLAGS that linking succeeds, but I had to explicitly configure -DWITH_VTK=OFF.

Update: Without adding the compiler flags, I manually removed /usr/lib/x86_64-linux-gnu/libpthread.a from the compiler invocation and then the target builds. I did not find a way to force cmake to not link pthreads dynamically. The CMAKE_FIND_LIBRARY_SUFFIXES get set to ".a" when building static libs. I tried switching this temporarily to ".so" for the find_packge(Threads) call, but that does not help. maybe because the lib is also brought in through another dependency such as OpenMP?

@themightyoarfish themightyoarfish added kind: compile error Type of issue status: triage Labels incomplete labels Sep 2, 2020
@kunaltyagi kunaltyagi added module: cmake platform: linux skill: cmake Skills/areas of expertise needed to tackle the issue needs: testing Specify why not closed/merged yet and removed status: triage Labels incomplete labels Sep 3, 2020
@guban
Copy link
Contributor

guban commented Sep 8, 2020

It looks like the problem is caused by the line

set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})

in file

cmake/pcl_options.cmake

I found that when trying to build pcl 1.11.1 as a static library. I'm getting this error:

CMake Error at /usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
Could NOT find OpenGL (missing: OPENGL_opengl_LIBRARY OPENGL_glx_LIBRARY)
Call Stack (most recent call first):
/usr/share/cmake/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
/usr/share/cmake/Modules/FindOpenGL.cmake:433 (FIND_PACKAGE_HANDLE_STANDARD_ARGS)
cmake/pcl_find_gl.cmake:10 (find_package)
CMakeLists.txt:458 (include)

My setup is

Linux - 5.4.60-gentoo - x86_64
gcc 9.3.0 (Gentoo 9.3.0-r1 p3) 
cmake 3.18.2.

and cmake is generally able to find OpenGL. I verified that by running cmake . on this simple test CMakeLists.txt:

project(MyProj)
cmake_minimum_required(VERSION 3.18)
find_package(OpenGL REQUIRED)

Adding find_package(OpenGL REQUIRED) just before the line

set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})

fixes the error, whereas adding find_package(OpenGL REQUIRED) just after that line does not fix anything.

Digging into the history revealed an interesting fact: in the case PCL_SHARED_LIBS==ON, a similar line

#  set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})

was commented in file cmake/pcl_options.cmake with commit message saying

Even in shared build Windows requires to find static libraries, issue #636

Well, it looks like even in static build Linux requires to find shared libraries. So, the line

set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})

must be deleted, and this should fix the problem.

@kunaltyagi
Copy link
Member

If you believe this resolves the issue, please issue a PR 🎉

@themightyoarfish
Copy link
Contributor Author

That may avoid the error, but through accepting dynamic libs as well, and I think they'll mostly be preferred if both dynamic and static versions are available. The result may be static libpcl, but which depends on many dynamic libs. Then the question becomes what the goal is exactly? Just have a static library, or one that minimizes shared runtime dependencies?

@kunaltyagi
Copy link
Member

kunaltyagi commented Sep 8, 2020

PCL's cmake allows each dependency to be explicitly chosen as static, so there's some control over that process (if that's what you're asking)

@guban
Copy link
Contributor

guban commented Sep 8, 2020

I'll prepare the PR soon.

In any case, pcl should not force users to choose only between "all-static" and "all-dynamic" alternatives. That is too rigid. A better solution is to support "I-dont-care" scenario by default, where pcl just compiles with whatever dependencies are found, making random choices if both static and dynamic versions of a dependency are available to choose from. If the user wants a control over how pcl dependencies are build, the user should use a package manager like conan or vcpkg.

A package manager represents each dependency of pcl, direct or indirect, is a separate package. Pcl may suggest the default settings for its dependencies, but the user has the ultimate control whether to build each individual package as a static or shared library, and what other options to choose for each package.

Considering this, PCL_SHARED_LIBS should control only the pcl library itself, but not its dependencies. Moreover, pcl cmake scripts should minimize control over how dependencies are built and how to find them. Ideally, for each dependency XXX, pcl should just invoke find_package(XXX REQUIRED) and use the XXX::XXX cmake target where needed. The corresponding FindXXX.cmake file should be provided by the user (or, rather, generated by the package manager on user's behalf).

@kunaltyagi
Copy link
Member

My CMake skills are pretty bad. PRs to augment are welcome 😄

🎊 awaiting PR 🎊

@larshg
Copy link
Contributor

larshg commented Sep 8, 2020

We have had some trouble mixing static and dynamic version of the libraries:

see #1601 (comment).

But it would be nice that it automatically find either static/dynamic of qhull, boost and flann.

They have some explicit variables like: PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 etc.

@guban
Copy link
Contributor

guban commented Sep 8, 2020

We have had some trouble mixing static and dynamic version of the libraries:

see #1601 (comment).

But it would be nice that it automatically find either static/dynamic of qhull, boost and flann.

They have some explicit variables like: PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 etc.

After reviewing #1601, my understanding is that the problem there was due to failure to call VTK_MODULE_INIT() for all VTK modules used by an application that was built as part of PCL. As pointed out in #1601 by @didory123, the solution to this problem is to let the application help to initialize VTK: add the needed VTK_MODULE_INIT() calls.

This initialization issue is not unique to VTK: it exists for any library, static or dynamic, which has to do a non-trivial initialization at startup. The only clean way to implement that is to provide in the library itself an initialization function, and then kindly ask any application that uses that library to call the provided initialization function before starting using the library. It is not possible (at least, on Windows) to cleanly auto-initialize a library without the help from the application. With dynamic libraries, one might attempt to perform the initialization from DllMain(), but that is very risky due to potential dll loader locks, and so any non-trivial initialization must not be called from DllMain(). With static libraries, even DllMain() is not an option, and the application really, really has to call the initialization function provided by the library. For VTK, this function is VTK_MODULE_INIT(). I'm using VTK 8.2.0, and I initialize it like this:

VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);

This works regardless whether VTK is built as static or dynamic library.

So, I think the problem in #1601 was more about proper initialization of VTK rather than about mixing static and dynamic versions of the libraries. As long as all pcl applications that use VTK make the needed VTK_MODULE_INIT() calls, they should work, regardless of whether VTK is static or dynamic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: compile error Type of issue module: cmake needs: testing Specify why not closed/merged yet platform: linux skill: cmake Skills/areas of expertise needed to tackle the issue
Projects
None yet
Development

No branches or pull requests

4 participants