9

I tried to reproduce minimal problem. When I run CMake+Make on Ubuntu I get error

funccpp.cpp:(.text+0x5): undefined reference to `FuncC'

i.e. exported function in C library is not found when importing in C++ library. When I try to manually compile using g++ main.cpp funcc.c funccpp.cpp it successfully compiles final program. How to fix CMake issue?

For reference, when I run nm libfuncc_lib.a I get line T FuncC (so symbol is external and defined in Text section), when I run nm libfunccpp_lib.a I get U FuncC (so symbol is Undefined and should be linked from outside).

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(Test C CXX)

set (SRC_CPP funccpp.cpp)
set (SRC_C funcc.c)
set (SRC_MAIN main.cpp)

add_library(funcc_lib STATIC ${SRC_C})
add_library(funccpp_lib STATIC ${SRC_CPP})
add_executable(prog ${SRC_MAIN})
target_link_libraries(prog funcc_lib funccpp_lib)

main.cpp

#include "funccpp.h"

int main() {
    FuncCPP();
    return 0;
}

funccpp.h

#ifndef FUNCCPP_H
#define FUNCCPP_H

void FuncCPP();

#endif

funccpp.cpp

#include "funcc.h"

void FuncCPP() {
    FuncC();
}

funcc.h

#ifndef FUNCC_H
#define FUNCC_H

#ifdef __cplusplus
extern "C" {
#endif

void FuncC();

#ifdef __cplusplus
}
#endif

#endif // FUNCC_H

funcc.c

#include "funcc.h"
#include <stdio.h>

void FuncC() {
    printf("Hello, World!\n");
}
Arty
  • 14,883
  • 6
  • 36
  • 69
  • 1
    Try using 'target_link_libraries(prog funccpp_lib funcc_lib)' instead of 'target_link_libraries(prog funcc_lib funccpp_lib)' since your C++ lib depdends on C lib. – Viktor Latypov Aug 07 '18 at 11:32
  • 1
    What happens if you switch the order of libraries to `target_link_libraries(prog funccpp_lib funcc_lib)`? – aschepler Aug 07 '18 at 11:32
  • 1
    Not sure about CMake and 'target_link_libraries', but for single-pass LD linker implementation it instructs the linker to search symbols for 'funccpp_lib' in 'funcc_lib', not vice versa. – Viktor Latypov Aug 07 '18 at 11:36

2 Answers2

11

The problem here is, that the linker relies on the order of the libraries. With

target_link_libraries(prog funcc_lib funccpp_lib)

It first links funcc_lib and then funccpp_lib. But it never gets back to funcc_lib. Since funccpp_lib depends on funcc_lib, you have to change the order of the libraries:

target_link_libraries(prog funccpp_lib funcc_lib)

For additional information, see this discussion.

Stanley F.
  • 1,846
  • 16
  • 29
  • Thanks! Issue fixed. But what to do with cases when there are two libraries A and B, where there is cyclic dependency - A needs some functions from B and vice versa? – Arty Aug 07 '18 at 11:43
  • 3
    @ArtyOneSoul Have a look at the link, I provided: Simply list the libs multiple times, i.e. `target_link_libraries(prog funccpp_lib funcc_lib funccpp_lib)` – Stanley F. Aug 07 '18 at 11:46
  • 2
    Even better, tell CMake that `funccpp_lib` depends on `funcc_lib`: `target_link_libraries(funccpp_lib funcc_lib)`. – John Aug 07 '18 at 12:59
0

Make cmake c link command as c++ commmand will solve the problem

SET(CMAKE_C_LINK_EXECUTABLE ${CMAKE_CXX_LINK_EXECUTABLE})
Jagger Yu
  • 577
  • 4
  • 5