0

Recently I used CLION to write C++ code. But an unexpected error occurred when I tried to run my project.

"D:\programming\Clion\CLion 2020.3.2\bin\cmake\win\bin\cmake.exe" --build D:\A_project\ray_tracing_cpp\cmake-build-debug --target ray_tracing_cpp -j 6
[1/1] Linking CXX executable ray_tracing_cpp.exe
FAILED: ray_tracing_cpp.exe 
cmd.exe /C "cd . && D:\A_ENVIRONMENT\MinGW\x86_64-8.1.0-release-posix-seh-rt_v6-rev0\mingw64\bin\c++.exe -g  CMakeFiles/ray_tracing_cpp.dir/main.cpp.obj CMakeFiles/ray_tracing_cpp.dir/vec3.cpp.obj -o ray_tracing_cpp.exe -Wl,--out-implib,libray_tracing_cpp.dll.a -Wl,--major-image-version,0,--minor-image-version,0  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
CMakeFiles/ray_tracing_cpp.dir/main.cpp.obj: In function `main':
D:/A_project/ray_tracing_cpp/main.cpp:5: undefined reference to `vec3::length() const'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

This error amazed me since I had checked my code and CMakeLists.txt carefully before I started to run my project.

my 'main.cpp':

#include "vec3.h"

int main() {
    vec3 v;
    v.length();
}

my 'vec3.h'

#ifndef RAY_TRACING_CPP_VEC3_H
#define RAY_TRACING_CPP_VEC3_H

struct vec3 {
    double x;
    double y;
    double z;

    vec3(double x, double y, double z) : x(x), y(y), z(z) {}
    vec3() : x(0.0), y(0.0), z(0.0) {}
    explicit vec3(double x) : x(x), y(x), z(x) {}

    ...

    inline double norm2() const;
    inline double length() const;
    inline double dot(const vec3& another) const;
    inline vec3 cross(const vec3& another) const;
    inline vec3 normalize() const;
    inline vec3 exp() const;
    inline vec3 pow(double param) const;
};


#endif //RAY_TRACING_CPP_VEC3_H

my 'vec3.cpp'

#include "vec3.h"
#include "cmath"

inline double vec3::norm2() const {
    return this->x * this->x + this->y * this->y + this->z * this->z;
}

inline double vec3::length() const {
    return sqrt(norm2());
}

inline double vec3::dot(const vec3& another) const {
    return this->x * another.x + this->y * another.y + this->z * another.z;
}

inline vec3 vec3::cross(const vec3 &another) const {
    return {
            this->y * another.z - this->z * another.y,
            this->z * another.x - this->x * another.z,
            this->x * another.y - this->y * another.x
    };
}

inline vec3 vec3::normalize() const {
    auto len = length();
    return *this / len;
}

vec3 vec3::exp() const
{
    return {std::exp(x), std::exp(y), std::exp(z)};
}

vec3 vec3::pow(double param) const
{
    return {std::pow(x, param), std::pow(y, param), std::pow(z, param)};
}

and my 'CMakeLists.txt'

cmake_minimum_required(VERSION 3.21)
project(ray_tracing_cpp)

set(CMAKE_CXX_STANDARD 14)

add_executable(ray_tracing_cpp main.cpp vec3.h vec3.cpp)

I really want to know what's going wrong with my project. I would greatly appreciate it if someone can help me find out the mistake! This error has been bothering me for a long time.

  • 1
    `inline` keyword means something completely different then you think for quite long time. Trash it. – Marek R Jul 19 '22 at 15:15
  • 1
    Note warring https://godbolt.org/z/Tvb5W87a3 – Marek R Jul 19 '22 at 15:23
  • If you want the compiler to consider inlining a function, you must supply the implementation in the header (otherwise remove the `inline`s as suggested by @MarekR). – wohlstad Jul 19 '22 at 15:27
  • Here it builds https://godbolt.org/z/Mz74bv8Te – Marek R Jul 19 '22 at 15:27
  • @wohlstad if everything is in single target linker can do it in any case. Having this in header file do not provide such warranty. Optimizer can do lots of cool stuff. – Marek R Jul 19 '22 at 15:29
  • @MarekR I was under the impression that in order to "encourage" the compiler to inline (when compiling other translation units) the implementation should better be in the header. Can we count on modern optimizers to do it otherwise ? Do you know specifically if MSVC is capable of it ? – wohlstad Jul 19 '22 at 15:39

0 Answers0