Skip to content

modify code to allow shared object used independently and some minor changes #7

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

hwyao
Copy link

@hwyao hwyao commented Mar 30, 2024

modify code to allow shared object used independently and some minor changes:

  • update the target ${PROJECT_NAME}-shared with correct shared object linking dependency on osqp and qpOASES.
  • Correspondingly, update the way of linking in example and tests.
  • Switch gcc argument style linking to target-based linking with add_library(IMPORTED)
  • remove add_dependencies() of a target over a ExternalProject, which actually does nothing.

add_library(qpoases_lib SHARED IMPORTED)
set_target_properties(qpoases_lib PROPERTIES
IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/lib/${CMAKE_FIND_LIBRARY_PREFIXES}qpOASES${CMAKE_SHARED_LIBRARY_SUFFIX}
IMPORTED_NO_SONAME TRUE
Copy link
Author

@hwyao hwyao Mar 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment 1:
The IMPORTED_NO_SONAME TRUE for qpOASES is that, libqpOASES.so has no SONAME. This might be a reason that here we directly uses the Makefile instead of CMakeLists.txt provided by the repo.
(SONAME can be check with readelf -d <library-name> | head -10 to compare libosqp.so and libqpOASES.so)

> readelf -d libosqp.so | head -10
Dynamic section at offset 0x1ad90 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000e (SONAME)             Library soname: [libosqp.so]
 0x000000000000000c (INIT)               0x4000
> readelf -d libqpOASES.so | head -10
Dynamic section at offset 0x75d38 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x14000

When not using the IMPORTED_NO_SONAME, the runtime dynamic linking of the library is based on the relative path, instead of the rpath. Simply speaking, when you try to run the library / executable in a folder that is not the folder that you run make command, the loading will be failed.

We can inspect this by running the ldd over the built liblcqpow.so:
(no fixing) inside build folder:

>~/Git/LCQPow/build$ ldd ./lib/liblcqpow.so 
        linux-vdso.so.1 (0x00007ffc4808e000)
        lib/libqpOASES.so (0x00007f62c680d000)
        ...

(no fixing) in some other folder:

>~/Git/LCQPow/build/lib$ ldd ./liblcqpow.so 
        linux-vdso.so.1 (0x00007ffe1cbef000)
        lib/libqpOASES.so => not found

(fixed) everywhere:

>:~/Git/LCQPow/build/lib$ ldd ./liblcqpow.so 
        linux-vdso.so.1 (0x00007ffca27b1000)
        libqpOASES.so => <HOME FOLDER>/Git/LCQPow/build/lib/libqpOASES.so (0x00007f8eeeb6f000)

Some helpful references:
https://cmake.org/cmake/help/latest/prop_tgt/IMPORTED_NO_SONAME.html
https://stackoverflow.com/questions/10199045/c-linker-missing-library-when-running-soname-behavior
https://stackoverflow.com/questions/68164903/cmake-to-link-external-library-with-import-soname-ro-import-location

@hwyao
Copy link
Author

hwyao commented Mar 30, 2024

We can use the folder and file sturcture provided in #6 as a simple test:

folder:
图片

CMakeLists.txt:

cmake_minimum_required(VERSION 3.24) # lower version like 3.2 also fine I think
project(LCQPow_test)

include(ExternalProject)
set(LCQPow_NAME "LCQPow")  
ExternalProject_Add(${LCQPow_NAME}
    GIT_REPOSITORY "https://github.com/hwyao/LCQPow"  
    GIT_TAG "main"                           # should be commit f29ee7b more precisely
    INSTALL_COMMAND ""
)

set(LCQPow_SOURCE_DIR ${CMAKE_BINARY_DIR}/${LCQPow_NAME}-prefix/src/${LCQPow_NAME})
set(LCQPow_BUILD_DIR ${CMAKE_BINARY_DIR}/${LCQPow_NAME}-prefix/src/${LCQPow_NAME}-build)

add_library(LCQPow_lib SHARED IMPORTED)
set_target_properties(LCQPow_lib PROPERTIES
  IMPORTED_LOCATION ${LCQPow_BUILD_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}lcqpow${CMAKE_SHARED_LIBRARY_SUFFIX}
)

include_directories(
    ${LCQPow_SOURCE_DIR}/include
    ${LCQPow_BUILD_DIR}/external/src/qpoases/include
    ${LCQPow_BUILD_DIR}/external/src/osqp/include
)

add_executable(${PROJECT_NAME}
    src/use_LCQPow.cpp
)
target_link_libraries(${PROJECT_NAME} PRIVATE
  LCQPow_lib
) 

add_library(${PROJECT_NAME}_lib SHARED
    src/use_LCQPow_lib.cpp
)
target_link_libraries(${PROJECT_NAME}_lib
  LCQPow_lib
)

Now only linking with shared library of LCQpow is totally fine.

@hallfjonas hallfjonas self-assigned this Apr 1, 2024
@hallfjonas
Copy link
Collaborator

Thanks for adding this pull request! Looks like a good improvement once we get everything working :)

I checked out this pull request, but I couldn't compile. Here is my output

~/LCQPow/build$ make
Scanning dependencies of target lcqpow-shared
[  1%] Building CXX object CMakeFiles/lcqpow-shared.dir/src/LCQProblem.cpp.o
In file included from /home/jonas/LCQPow/include/LCQProblem.hpp:26,
                 from /home/jonas/LCQPow/src/LCQProblem.cpp:23:
/home/jonas/LCQPow/include/Utilities.hpp:27:14: fatal error: osqp.h: No such file or directory
   27 |     #include <osqp.h>
      |              ^~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/lcqpow-shared.dir/build.make:63: CMakeFiles/lcqpow-shared.dir/src/LCQProblem.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:319: CMakeFiles/lcqpow-shared.dir/all] Error 2
make: *** [Makefile:84: all] Error 2

Currently trying to investigate what's happening here.

@hwyao
Copy link
Author

hwyao commented Apr 1, 2024

Not very sure why things works differently, Maybe because my cmake version is 3.28.3 so something works differently? But surely it has something to do with the include things, especially here:

I remove the project-based include

include_directories(${PROJECT_NAME}
    SYSTEM ${qpoases_include}
    SYSTEM ${osqp_include}
)

To target-based include target_include_directories.

I realize a mistake I made here (some bad / not very well written PUBLIC and PRIVATE attribute). Not very sure if this causes this problem in your machine. If it still cannot work, we can re-introduce the project-based include and I think this will go away.

@hallfjonas hallfjonas linked an issue Apr 1, 2024 that may be closed by this pull request
@hwyao
Copy link
Author

hwyao commented Apr 1, 2024

Some extra hints:

add_depencency([target] [ExternalProject]) is meaningless, but add_depencency([target] [imported_target]) is totally fine.
So as a potential (future) improvement

add_dependencies(
    ${PROJECT_NAME}-shared
    qpoases_lib
    osqp_lib
)

for this and other targets is helpful.

Running make is actually the same. But it helps when someone would like run commands like make -j4. Not very sure if you want to implement it now.

Helpful references: https://stackoverflow.com/questions/31222734/cmake-externalproject-add-and-parallel-builds

@hwyao
Copy link
Author

hwyao commented Apr 29, 2024

Some quick comments: I still can't the the parallel problem working (catkin will automatically run things in parallel so it will get some error for the first time. But running catkin for the second time will solve this problem).

But I am a bit busy in these few days, I will take a look over this later calmly. Anyway this is not a major problem.

p.s.
the repo using this solver as planner https://github.com/hwyao/LCQP_planner_core is public now but I also don't have time to write docs and release it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Issue: Improvement over compiled shared object.
2 participants