3

As written above, I try to compile one native library to use it within JNI. But I get the following error:

/src/main/cpp/app1.cpp.o: multiple definition of '...'

/src/main/cpp/mylib.cpp.o: previous definition here

This only appears when I use the .hh data, which "include full template code". The stuff that is multiple defined is in a precompiled library, with the headers included through 'HEADER_FILES'.

Here is my CMakeLists.txt:

set(HEARDER_SRC_DIRECTORY ${CMAKE_SOURCE_DIR}/../../header/src)
include_directories(${HEADER_SRC_DIRECTORY})
set(HEADER_FILES ${HEADER_SRC_DIRECTORY}/header1.h ${HEADER_SRC_DIRECTORY}/header2.h ${HEADER_SRC_DIRECTORY}/header1.hh ${HEADER_SRC_DIRECTORY}/header2.hh)
add_library(
    mylib
    SHARED
    src/main/mylib.cpp
    ${HEADER_FILES}
    src/main/app1.h
    src/main/app1.cpp
)
find_library(
    log-lib
    log 
)
target_link_libraries(  
    mylib
    ${CMAKE_SOURCE_DIR}/libs/liby.a     # precompiled lib
    ${CMAKE_SOURCE_DIR}/libs/libz.a     # precompiled lib
    ${log-lib}
)

How can I fix that? As I understand it each .cpp gets compiled on its own before they get linked and then they already have the same definitions. Of course, they have, that is why I link app1 in mylib, so I can access some functions. Where is my logical error? Will splitting them up help?

What mylib.cpp is including:

#include <jni.h>
#include <string>
#include "app1.h"

What app1.h is including:

#include "jni.h"
#include "header1.h"
#include "header1.hh"
#include <vector>
#include <cmath>
#include <iostream>
#include <fstream>
#include <string>

Here is one part of the definitions that is double (inside the header1.h):

namespace nsp {

Class::Class(Able& able, std::string name)
  : _able(able), _iBlock(0), _size(0), _name(name)
{ }

void Serializer::resetCounter()
{ 
  _iBlock = 0;
}

....

}
Community
  • 1
  • 1
  • Look up the "one definition rule". – Jesper Juhl Jul 30 '18 at 22:17
  • Thanks that is quite basic, and I get that, but what I don't get where in my code it could be like that. If I use this library outside Android Studio, it works. As soon as I link it with that header1.hh in CMake, it doesn't. mylib.cpp does only call one function of this lib and does not have more content. –  Jul 30 '18 at 22:25
  • Also read https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix#12573818 – Jesper Juhl Jul 30 '18 at 22:26
  • `This only appears when I use the .hh data, which "include full template code"` - Show that file (in form of [mcve]). Otherwise, revealing your problem is just a *guessing game*. – Tsyvarev Jul 30 '18 at 22:28
  • Well I guess it is, because in these contexts, with .hh, there are already some definitions (see question) inside the header. So this will get compiled with mylib and app1, so it is multiple then. Is there a way to change that without touching the lib? –  Jul 30 '18 at 22:50
  • Yes, a header file shouldn't contain function's **definitions** (except `static inline` ones). Only *declarations* are allowed. – Tsyvarev Jul 30 '18 at 22:51
  • Thank you very much, so concluding these definitions should be removed there somehow to make it work. –  Jul 30 '18 at 23:06

1 Answers1

1

The definition of Serializer::resetCounter() is not inlined. This means each translation unit (source file) that includes "header1.h" (directly or indirectly) will have its own definition of that function. This can lead the compiler to complain about violations of the one-definition rule.

If your intention is to make that an inlined function in the header file, you may do so by moving the definition into the class Serializer itself, or by using the inline keyword.

inline void Serializer::resetCounter()
{ 
  _iBlock = 0;
}
jxh
  • 69,070
  • 8
  • 110
  • 193
  • Works for me, if anybody else does not know what 'inline' means: https://stackoverflow.com/questions/156438/what-does-it-mean-for-a-c-function-to-be-inline –  Jul 31 '18 at 18:36