0

I have a library B that privately depends on an external static library A.

I would like library B to statically link to library A such that any library that links to library B then doesn't need to link to library A; and even library to be hidden outside of library B.

Here is a minimal example.

A/A.hpp

namespace A
{

int A();

}

A/A.cpp

include "A.hpp"

using namespace A;

int A::A()
{
    return 1;
}

I get A.a with

g++ -c A.cpp
ar rvs A.a A.o

Now A.a is considered as an external library.

B/B.hpp

amespace B
{

int B();

}

B/B.cpp

#include "B.hpp"

#include "A.hpp"

using namespace B;

int B::B()
{
    return A::A();
}

B/CMakeLists.txt

cmake_minimum_required(VERSION 3.15.0)

project(B LANGUAGES CXX)

add_library(A STATIC IMPORTED)
target_include_directories(A INTERFACE ../A)
set_target_properties(A PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../A/A.a)

add_library(B_B)
target_sources(B_B PRIVATE B.cpp)
target_link_libraries(B_B PRIVATE A)

add_executable(B_main)
target_sources(B_main PRIVATE main.cpp)
target_link_libraries(B_main PUBLIC B_B)

Now If I run

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -- VERBOSE=1

-- The CXX compiler identification is GNU 13.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: /home/XXX/test/B/build

/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -S/home/XXX/test/B -B/home/XXX/test/B/build --check-build-system CMakeFiles/Makefile.cmake 0
/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_progress_start /home/XXX/test/B/build/CMakeFiles /home/XXX/test/B/build//CMakeFiles/progress.marks
/usr/bin/gmake  -f CMakeFiles/Makefile2 all
gmake[1] : on entre dans le répertoire « /home/XXX/test/B/build »
/usr/bin/gmake  -f CMakeFiles/B_B.dir/build.make CMakeFiles/B_B.dir/depend
gmake[2] : on entre dans le répertoire « /home/XXX/test/B/build »
cd /home/XXX/test/B/build && /home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_depends "Unix Makefiles" /home/XXX/test/B /home/XXX/test/B /home/XXX/test/B/build /home/XXX/test/B/build /home/XXX/test/B/build/CMakeFiles/B_B.dir/DependInfo.cmake "--color="
gmake[2] : on quitte le répertoire « /home/XXX/test/B/build »
/usr/bin/gmake  -f CMakeFiles/B_B.dir/build.make CMakeFiles/B_B.dir/build
gmake[2] : on entre dans le répertoire « /home/XXX/test/B/build »
[ 25%] Building CXX object CMakeFiles/B_B.dir/B.cpp.o
/usr/bin/c++  -isystem /home/XXX/test/B/../A -O3 -DNDEBUG -MD -MT CMakeFiles/B_B.dir/B.cpp.o -MF CMakeFiles/B_B.dir/B.cpp.o.d -o CMakeFiles/B_B.dir/B.cpp.o -c /home/XXX/test/B/B.cpp
[ 50%] Linking CXX static library libB_B.a
/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -P CMakeFiles/B_B.dir/cmake_clean_target.cmake
/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_link_script CMakeFiles/B_B.dir/link.txt --verbose=1
/usr/bin/ar qc libB_B.a CMakeFiles/B_B.dir/B.cpp.o
/usr/bin/ranlib libB_B.a
gmake[2] : on quitte le répertoire « /home/XXX/test/B/build »
[ 50%] Built target B_B
/usr/bin/gmake  -f CMakeFiles/B_main.dir/build.make CMakeFiles/B_main.dir/depend
gmake[2] : on entre dans le répertoire « /home/XXX/test/B/build »
cd /home/XXX/test/B/build && /home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_depends "Unix Makefiles" /home/XXX/test/B /home/XXX/test/B /home/XXX/test/B/build /home/XXX/test/B/build /home/XXX/test/B/build/CMakeFiles/B_main.dir/DependInfo.cmake "--color="
gmake[2] : on quitte le répertoire « /home/XXX/test/B/build »
/usr/bin/gmake  -f CMakeFiles/B_main.dir/build.make CMakeFiles/B_main.dir/build
gmake[2] : on entre dans le répertoire « /home/XXX/test/B/build »
[ 75%] Building CXX object CMakeFiles/B_main.dir/main.cpp.o
/usr/bin/c++   -O3 -DNDEBUG -MD -MT CMakeFiles/B_main.dir/main.cpp.o -MF CMakeFiles/B_main.dir/main.cpp.o.d -o CMakeFiles/B_main.dir/main.cpp.o -c /home/XXX/test/B/main.cpp
[100%] Linking CXX executable B_main
/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_link_script CMakeFiles/B_main.dir/link.txt --verbose=1
/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/B_main.dir/main.cpp.o -o B_main  libB_B.a /home/XXX/test/B/../A/A.a
gmake[2] : on quitte le répertoire « /home/XXX/test/B/build »
[100%] Built target B_main
gmake[1] : on quitte le répertoire « /home/XXX/test/B/build »
/home/XXX/Programmes/cmake-3.29.2-linux-x86_64/bin/cmake -E cmake_progress_start /home/XXX/test/B/build/CMakeFiles 0

In particular, the compilation of the main executable includes the dependency to library A:

/usr/bin/c++ -O3 -DNDEBUG CMakeFiles/B_main.dir/main.cpp.o -o B_main  libB_B.a /home/XXX/test/B/../A/A.a

Is there a way to avoid this?

5
  • 1
    If both library A and library B are static then you must specify them both in the final linker command line, regardless of whether you are linking a dynamic library or an executable. Commented Dec 18, 2024 at 13:43
  • @trojanfoe so is there no way to hide library A from the other libraries depending on B? Commented Dec 18, 2024 at 13:57
  • The only way I can think of is to merge the two libraries, given static libraries are just archives of object files (.o). Commented Dec 18, 2024 at 15:20
  • Is this a case for making A an OBJECT library? https://stackoverflow.com/questions/75305718/why-is-there-a-distinction-between-linking-with-target-object-libraries-and-libr Commented Dec 18, 2024 at 17:33
  • 1
    Cmake is just a build system. It sets up your build using specified toolchain, the toolchain still handles actual compilation and linking. When you link anything with A, you will need to include A in linker command, whether as a separate library or archived together with others. You can try to archive A into B_B, which would hide everything - as long as you truly never link with both A and B_B. Commented Dec 18, 2024 at 23:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.