Reputation: 1990
Running along the makefile, I get to this:
cc client.o MurmurHash3.o libstorage.a -Wall -lreadline -pthread -o client
MurmurHash3.o: In function `MurmurHash3_x64_128':
/home/evantandersen/mount/src/MurmurHash3.c:59: undefined reference to `rotl64'
/home/evantandersen/mount/src/MurmurHash3.c:106: undefined reference to `fmix'
And, MurmurHash3.c
:
inline uint64_t rotl64 ( uint64_t x, int8_t r )
{
return (x << r) | (x >> (64 - r));
}
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
inline uint64_t fmix ( uint64_t k )
{
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
return k;
}
//-----------------------------------------------------------------------------
void MurmurHash3_x64_128 ( const void * key, const int len,
const uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const int nblocks = len / 16;
uint64_t h1 = seed;
uint64_t h2 = seed;
const uint64_t c1 = 0x87c37b91114253d5;
const uint64_t c2 = 0x4cf5ad432745937f;
//----------
// body
const uint64_t * blocks = (const uint64_t *)(data);
for(int i = 0; i < nblocks; i++)
{
uint64_t k1 = blocks[i*2+0];
uint64_t k2 = blocks[i*2+1];
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
h1 = rotl64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
h2 = rotl64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
//----------
// tail
const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
uint64_t k1 = 0;
uint64_t k2 = 0;
switch(len & 15)
{
case 15: k2 ^= ((uint64_t)tail[14]) << 48;
case 14: k2 ^= ((uint64_t)tail[13]) << 40;
case 13: k2 ^= ((uint64_t)tail[12]) << 32;
case 12: k2 ^= ((uint64_t)tail[11]) << 24;
case 11: k2 ^= ((uint64_t)tail[10]) << 16;
case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
case 9: k2 ^= ((uint64_t)tail[ 8]) << 0;
k2 *= c2; k2 = rotl64(k2,33); k2 *= c1; h2 ^= k2;
case 8: k1 ^= ((uint64_t)tail[ 7]) << 56;
case 7: k1 ^= ((uint64_t)tail[ 6]) << 48;
case 6: k1 ^= ((uint64_t)tail[ 5]) << 40;
case 5: k1 ^= ((uint64_t)tail[ 4]) << 32;
case 4: k1 ^= ((uint64_t)tail[ 3]) << 24;
case 3: k1 ^= ((int64_t)tail[ 2]) << 16;
case 2: k1 ^= ((uint64_t)tail[ 1]) << 8;
case 1: k1 ^= ((uint64_t)tail[ 0]) << 0;
k1 *= c1; k1 = rotl64(k1,31); k1 *= c2; h1 ^= k1;
};
//----------
// finalization
h1 ^= len; h2 ^= len;
h1 += h2;
h2 += h1;
h1 = fmix(h1);
h2 = fmix(h2);
h1 += h2;
h2 += h1;
((uint64_t*)out)[0] = h1;
((uint64_t*)out)[1] = h2;
}
Both rotl64
and fmix
are defined in the same file AND above the function MurmurHash3_x64_128
.
Upvotes: 3
Views: 811
Reputation: 171263
If you're compiling as C99 then the compiler doesn't have to use an inline
function definition, but GCC will when optimising. When not optimising it assumes there is a normal extern
definition somewhere in the program, and that's what it tries to link to.
By defining it extern inline
you make it the extern
definition, so it will be used when not optimised, by calls in the same or different translation units.
By defining it static inline
you make it a static
definition, so it will be used when not optimised, by calls in the same translation unit only. That inline
definition cannot be used to resolve calls in other translation units.
See http://www.greenend.org.uk/rjk/tech/inline.html for more details.
Upvotes: 5
Reputation: 1990
For some reason, changing the definitions from
inline type name(parameters)
to
inline static type name(paramaters)
Solved the problem. Not sure if this is a compiler bug, I'd have to read the C standard.
EDIT: gcc v4.6.3, GNU ld v2.22
Turning on optimization solves the error as well (without adding the static keyword), so I'm not entirely sure what's going on.
Upvotes: 0