Search code examples
makefilecmakeextern

CMake undefined symbol to extern


I am trying to convert a Makefile project to a CMake project. The project has a file a.cxx that has an extern function declaration:

extern int shared_int;
extern void say_hello(void);

int main(int argc, char ** argv)
{
        say_hello();
        return 0;
}

The definition to that function is in b.c:

#include <stdio.h>

int shared_int = 5;

void say_hello()
{
        printf("Hello!\n");
}

and my CMakeLists.txt is as follows:

project(extern_example)

add_executable(extern_example a.cxx b.c)

If I change the printf to be used in a.cc to print shared_int, it works fine, but when I try to use say_hello from a.cxx, I get

CMakeFiles/extern_example.dir/a.cxx.o: In function `main':
a.cxx:(.text+0x10): undefined reference to `say_hello()'
collect2: error: ld returned 1 exit status
CMakeFiles/extern_example.dir/build.make:120: recipe for target 'extern_example' failed
make[2]: *** [extern_example] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/extern_example.dir/all' failed
make[1]: *** [CMakeFiles/extern_example.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

The error makes it look like b.c is not being linked correctly in the executable, but then why would shared_int be available?

I have tried to make this as general as possible, but the files in question are on BitBucket (Makefile and analyzer.c/h are of interest) and here is the file that I'm calling A.cxx. I have also trimmed off other includes and links in the compile commands, but I can post those if necessary.


Solution

  • The problem was with function definitions in a.cxx defined as

    extern void f(void);
    

    rather than

    extern "C" void f(void);
    

    or

    extern "C" {
        void f(void);
    }
    

    Without specifying the C-style extern, the compiler mangles the function names, which are unable to be read by b.c.