I have a large library B that performs some operations on a configuration object MY_CONFIG. This library is linked against an even larger library C that provides the main functionality. In the end, C is linked against the executable main.
The configuration object MY_CONFIG is unique for each computing unit. Since the goal is to produce one C library for all systems, I am currently trying to produce an additional library A that only contains the defined configuration object.
In other words, all computing units eventually receive the same C, but different A libraries.
The problem is, however, that I get an undefined reference linker error when trying to link main against C and A.
Let's illustrate the example with some code:
A.cpp
#include "B.hpp"
Config MY_CONFIG = {
.id=2
};
B.hpp
int get_config_id ();
typedef struct Config {
int id;
} Config;
B.cpp
#include "B.hpp"
extern Config MY_CONFIG;
int get_config_id () {
Config work = MY_CONFIG;
return work.id;
}
C.hpp
void print_config();
C.cpp
#include "B.hpp"
#include <iostream>
void print_config() {
std::cout << "Config ID: " << get_config_id() << std::endl;
}
main.cpp
#include <iostream>
#include "C.hpp"
int main() {
print_config();
return 0;
}
CMakeLists.txt
project(config)
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread")
add_library(A STATIC A/A.cpp)
target_include_directories(A PUBLIC B)
add_library(B STATIC B/B.cpp)
target_include_directories(B PUBLIC B)
add_library(C STATIC C/C.cpp)
target_include_directories(C PUBLIC C)
target_link_libraries(C B)
add_executable(main main.cpp)
# Apparently, this is not possible. But why?
target_link_libraries(main C A)
As you can see, I use the extern keyword for MY_CONFIG in B.cpp. My intuition was that it is resolved once building the executable main. Since the definition of MY_CONFIG is in A.cpp, I also link main against A. The following error shows up during compilation:
/usr/bin/ld: libB.a(B.cpp.o): in function `get_config_id()':
B.cpp:(.text+0xa): undefined reference to `MY_CONFIG'
collect2: error: ld returned 1 exit status
If I linked A against C, then it works perfectly fine. But this is something that I want to avoid because I'd need to deliver individual C's for all computing systems. An important side note: I can only work with static libraries (no shared objects).
Is my intention generally not possible or what do I miss?