1

I built a static executable with CMake.Here's my CMakeLists.txt

cmake_minimum_required(VERSION 3.25)
project(tmp2)

set(CMAKE_CXX_STANDARD 20)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_EXE_LINKER_FLAGS "-static")
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")

add_executable(tmp2 main.cpp)

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++")

target_link_libraries(${PROJECT_NAME}
    PUBLIC /usr/lib/x86_64-linux-gnu/libboost_chrono.a
    PUBLIC /usr/lib/x86_64-linux-gnu/libboost_date_time.a
    PUBLIC /usr/lib/x86_64-linux-gnu/libboost_filesystem.a
    PUBLIC /usr/lib/x86_64-linux-gnu/libboost_thread.a
    PUBLIC /usr/lib/x86_64-linux-gnu/libboost_atomic.a
)

target_include_directories(${PROJECT_NAME}
    PUBLIC /usr/local/include
    PUBLIC /usr/include/
    PUBLIC /usr/include/opencv4
)

But target_link_libraries looked kind of ugly, so I decided to use target_link_directories so I don't have write the full path to all static libraries in target_link_libaries. So I added the following code to my CMakeLists.txt.

target_link_directories(${PROJECT_NAME}
    PUBLIC /usr/lib/x86_64-linux-gnu/
    PUBLIC /usr/local/lib/
)

But after I added target_link_directories, CMake tried to link against dynamic libraries, and I got this error:

/usr/bin/ld: attempted static link of dynamic object `/usr/lib/gcc/x86_64-linux-gnu/13/libstdc++.so'
/usr/bin/ld: attempted static link of dynamic object `/lib/x86_64-linux-gnu/libm.so.6'
/usr/bin/ld: attempted static link of dynamic object `/lib/x86_64-linux-gnu/libmvec.so.1'
/usr/bin/ld: attempted static link of dynamic object `/lib/x86_64-linux-gnu/libc.so.6'
/usr/bin/ld: attempted static link of dynamic object `/lib64/ld-linux-x86-64.so.2'
collect2: error: ld returned 1 exit status

How can I build the static executable without using the full path to all static libraries?

Askr Askr
  • 25
  • 3
  • Use imported targets? I.e. `find_package(Boost REQUIRED chrono date_time filesystem thread atomic) target_link_libraries(tmp2 PRIVATE Boost::date_time Boost::...)` – Osyotr Aug 31 '23 at 07:13
  • Just tried that and I got this error: `/usr/bin/ld: attempted static link of dynamic object /usr/lib/x86_64-linux-gnu/libboost_chrono.so.1.74.0` – Askr Askr Aug 31 '23 at 07:15
  • `set(Boost_USE_STATIC_LIBS ON)` before calling `find_package`? https://cmake.org/cmake/help/latest/module/FindBoost.html#other-variables – Osyotr Aug 31 '23 at 07:30
  • Didn't work. That's not the only problem. What if I wanna use libraries other than Boost as well? – Askr Askr Aug 31 '23 at 07:36
  • https://stackoverflow.com/questions/63435382/find-package-for-a-static-library-instead-of-a-shared-library asked already 3 years ago, and surprisingly no good answer to this ... – pptaszni Aug 31 '23 at 07:47
  • Wait a sec. Does that mean `find_package` always finds shared libraries only? – Askr Askr Aug 31 '23 at 07:49
  • No, `find_package` doesn't understand the concept of shared/static. It just looks for `FindXXX.cmake` files and "executes" them. Then it is up to the library provider to set the correct `XXX_LIBRARIES` variables pointing to the static/shared libs. E.g. [spdlog](https://github.com/gabime/spdlog/blob/v1.x/CMakeLists.txt#L62) library can be compiled as shared or static, then installed, and then when you `find_package`, it will give you shared/static libs depending on how you compiled and installed it before. – pptaszni Aug 31 '23 at 07:58
  • If you know the name of the library and want to tell the **linker** to prefer static libraries instead of dynamic, then see [that question](https://stackoverflow.com/questions/16991225/cmake-and-static-linking). If you want `find_library` to prefer static library, then setting `CMAKE_FIND_LIBRARY_SUFFIXES` is a correct way. If you want `find_package` to prefer static libraries, then it is **package-specific**. Setting `CMAKE_FIND_LIBRARY_SUFFIXES` could work for some packages but could be ignored for others. So, which of "static linking" problem you are asking about? – Tsyvarev Aug 31 '23 at 09:12

0 Answers0