简体   繁体   中英

Trouble with linking in Makefile

If I try and compile the makefile in this plea for help, the terminal gives me the following for all my object files:

linker input file unused because linking not done

, and I can't for the life of me figure out how to compile it so that I can create the executable. What I've tried is:

Removing -c, so it looks like

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^

, which gives me a boatload of cygwin errors, so that's not the solution AFAIK. Here's a list of the errors, without all the duplicates:

/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x0): multiple definition of `Vector3D::Vector3D()'; main.o:main.cpp:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x32): multiple definition of `Vector3D::Vector3D(float, float, float)'; main.o:main.cpp:(.text+0x32): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x76): multiple definition of `Vector3D::getX() const'; main.o:main.cpp:(.text+0x76): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x88): multiple definition of `Vector3D::getY() const'; main.o:main.cpp:(.text+0x88): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x9c): multiple definition of `Vector3D::getZ() const'; main.o:main.cpp:(.text+0x9c): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0xb0): multiple definition of `Vector3D::operator*(Vector3D) const'; main.o:main.cpp:(.text+0xb0): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x106): multiple definition of `Vector3D::operator%(Vector3D) const'; main.o:main.cpp:(.text+0x106): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x1d4): multiple definition of `Vector3D::operator+(Vector3D) const'; main.o:main.cpp:(.text+0x1d4): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x256): multiple definition of `Vector3D::operator-(Vector3D) const'; main.o:main.cpp:(.text+0x256): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x2d8): multiple definition of `Vector3D::operator*(float) const'; main.o:main.cpp:(.text+0x2d8): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x344): multiple definition of `Vector3D::operator/(float) const'; main.o:main.cpp:(.text+0x344): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x3b0): multiple definition of `Vector3D::Magnitude()'; main.o:main.cpp:(.text+0x3b0): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x418): multiple definition of `Vector3D::Normal()'; main.o:main.cpp:(.text+0x418): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x59c): multiple definition of `Vector3D::Matrixed()'; main.o:main.cpp:(.text+0x59c): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x5ea): multiple definition of `Vector3D::~Vector3D()'; main.o:main.cpp:(.text+0x5ea): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x5f6): multiple definition of `Matrix3D::Matrix3D()'; main.o:main.cpp:(.text+0x5f6): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x666): multiple definition of `Matrix3D::Matrix3D(Vector3D, Vector3D, Vector3D)'; main.o:main.cpp:(.text+0x666): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x6ec): multiple definition of `Matrix3D::Matrix3D(float, float, float, float, float, float, float, float, float)'; main.o:main.cpp:(.text+0x6ec): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x768): multiple definition of `Matrix3D::operator*(Matrix3D)'; main.o:main.cpp:(.text+0x768): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x876): multiple definition of `Matrix3D::rotateX(float)'; main.o:main.cpp:(.text+0x876): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x920): multiple definition of `Matrix3D::rotateY(float)'; main.o:main.cpp:(.text+0x920): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0x9d0): multiple definition of `Matrix3D::rotateZ(float)'; main.o:main.cpp:(.text+0x9d0): first defined here
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0xa7c): multiple definition of `operator*(Vector3D const&, Matrix3D const&)'; main.o:main.cpp:(.text+0xa7c): first defined here   
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.text+0xbea): multiple definition of `Matrix3D::~Matrix3D()'; main.o:main.cpp:(.text+0xbea): first defined here

I have

#ifndef
#define

#endif

in all the hpp files, so I can't say why it's complaining about multiple definitions.

Separating out the -c and -o into their own things,

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -c $@ $^

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^

, which was no different from removing the -c.

Removing -o, so it looks like:

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -c $@ $^

, which makes it complain that Raytracer doesn't exist as a file or directory. (think I know why)

Placing out

%.o: %.cc
    $(CC) $(CFLAGS) -c -o $@ $<

, which makes nothing change, so I can't seem to understand how to make that work. And I can't find anything that helps me understand how to make it work.

Writing out the individual compilation steps above or below the $(NAME): $(OBJECTS) thing, for example

main.o: main.cc
    $(CC) $(CFLAGS) -c $@ $<

, which just makes it tell me that there's "No rule to make target 'main.cc', needed by 'main.o'. Stop.".

Placing out

$(OBJECTS): %.o: %.cc
    $(CC) $(CFLAGS) -c $@ $<

, which also doesn't seem to do anything.

Changing $^ into $<, which does nothing for me other than reduce the amount of "linking not done" messages I recieve.

The Makefile:

DEBUG=false
CC=gcc
CFLAGS=-Wall -pedantic -std=c18
NAME=Raytracer
OBJECTS=main.o OBB.o Plane.o Ray.o Shape.o Sphere.o Triangle.o
RM=rm -f

ifeq    ($(DEBUG),true)
    CFLAGS += -g
else
    CFLAGS += -O2
endif

default: all

all: $(NAME)

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -c -o $@ $^

.PHONY: clean

clean:
    $(RM) *.o $(NAME) $(OBJECTS)

Edit: ok, it was literally just -c that was the issue and it's my code that needs debugging now.

The Vector3D header:

#ifndef VECTOR3D_HPP
#define VECTOR3D_HPP

#include <cmath>

class Vector3D
{
    private:
        float x, y, z;
    public:
        Vector3D();
        Vector3D(float xCoord, float yCoord, float zCoord);
        
        float getX() const;
        float getY() const;
        float getZ() const;
    
        float operator*(Vector3D v2) const;
        Vector3D operator%(Vector3D v2) const;
        Vector3D operator+(Vector3D v2) const;
        Vector3D operator-(const Vector3D v2) const;
        Vector3D operator*(float mult) const;
        Vector3D operator/(float div) const;
        float Magnitude();
        Vector3D Normal();
        float& Matrixed();
        
        ~Vector3D();
};

Vector3D::Vector3D() {x=0.0f, y=0.0f, z=0.0f;}
Vector3D::Vector3D(float xCoord, float yCoord, float zCoord) {x=xCoord, y=yCoord, z=zCoord;}

float Vector3D::getX() const {return x;}
float Vector3D::getY() const {return y;}
float Vector3D::getZ() const {return z;}

float Vector3D::operator*(Vector3D v2) const {return x*v2.x + y*v2.y + z*v2.z;}

Vector3D Vector3D::operator%(Vector3D v2) const
{
    Vector3D res;
    res.x = y*v2.z - z*v2.y;
    res.y = z*v2.x - x*v2.z;
    res.z = x*v2.y - y*v2.x;
    return res;
}

Vector3D Vector3D::operator+(Vector3D v2) const
{
    Vector3D res;
    res.x = x + v2.x;
    res.y = y + v2.y;
    res.z = z + v2.z;
    return res;
}

Vector3D Vector3D::operator-(Vector3D v2) const
{
    Vector3D res;
    res.x = x - v2.x;
    res.y = y - v2.y;
    res.z = z - v2.z;
    return res;
}

Vector3D Vector3D::operator*(float mult) const
{
    Vector3D res;
    res.x = x*mult;
    res.y = y*mult;
    res.z = z*mult;
    return res;
}

Vector3D Vector3D::operator/(float div) const
{
    Vector3D res;
    res.x = x/div;
    res.y = y/div;
    res.z = z/div;
    return res;
}

float Vector3D::Magnitude() {return sqrt(x*x + y*y + z*z);}

Vector3D Vector3D::Normal()
{
    Vector3D res;
    res.x = x/sqrt(x*x + y*y + z*z);
    res.y = y/sqrt(x*x + y*y + z*z);
    res.z = z/sqrt(x*x + y*y + z*z);
    return res;
}

float& Vector3D::Matrixed()
{
    float list[3] ={getX(), getY(), getZ()};
    float& ref = *list;
    return ref;
}

Vector3D::~Vector3D(){}

#endif

What I took out from the hpp and put inside the Vector3D file:

Vector3D::Vector3D() {x=0.0f, y=0.0f, z=0.0f;}
Vector3D::Vector3D(float xCoord, float yCoord, float zCoord) {x=xCoord, y=yCoord, z=zCoord;}

float Vector3D::getX() const {return x;}
float Vector3D::getY() const {return y;}
float Vector3D::getZ() const {return z;}

float Vector3D::operator*(Vector3D v2) const {return x*v2.x + y*v2.y + z*v2.z;}

Vector3D Vector3D::operator%(Vector3D v2) const
{
    Vector3D res;
    res.x = y*v2.z - z*v2.y;
    res.y = z*v2.x - x*v2.z;
    res.z = x*v2.y - y*v2.x;
    return res;
}

Vector3D Vector3D::operator+(Vector3D v2) const
{
    Vector3D res;
    res.x = x + v2.x;
    res.y = y + v2.y;
    res.z = z + v2.z;
    return res;
}

Vector3D Vector3D::operator-(Vector3D v2) const
{
    Vector3D res;
    res.x = x - v2.x;
    res.y = y - v2.y;
    res.z = z - v2.z;
    return res;
}

Vector3D Vector3D::operator*(float mult) const
{
    Vector3D res;
    res.x = x*mult;
    res.y = y*mult;
    res.z = z*mult;
    return res;
}

Vector3D Vector3D::operator/(float div) const
{
    Vector3D res;
    res.x = x/div;
    res.y = y/div;
    res.z = z/div;
    return res;
}

float Vector3D::Magnitude() {return sqrt(x*x + y*y + z*z);}

Vector3D Vector3D::Normal()
{
    Vector3D res;
    res.x = x/sqrt(x*x + y*y + z*z);
    res.y = y/sqrt(x*x + y*y + z*z);
    res.z = z/sqrt(x*x + y*y + z*z);
    return res;
}

float& Vector3D::Matrixed()
{
    float list[3] ={getX(), getY(), getZ()};
    float& ref = *list;
    return ref;
}

Vector3D::~Vector3D(){}

The Matrix3D header:

#ifndef MATRIX3D_HPP
#define MATRIX3D_HPP

#include "3DVector.hpp"

class Matrix3D
{
    private:

    public:
                  //[Row][Col]
        float elements[3][3];
        Matrix3D();
        Matrix3D(Vector3D u, Vector3D v, Vector3D w);
        Matrix3D(float xx, float yx, float zx,
                 float xy, float yy, float zy,
                 float xz, float yz, float zz);
        Matrix3D operator*(Matrix3D m2);

        Matrix3D rotateX(float phi);
        Matrix3D rotateY(float theta);
        Matrix3D rotateZ(float psi);
        ~Matrix3D();
};

Matrix3D::Matrix3D(){float elements[3][3] = {{1.0f,0.0f,0.0f}, {0.0f,1.0f,0.0f}, {0.0f,0.0f,1.0f}};}
Matrix3D::Matrix3D(Vector3D u, Vector3D v, Vector3D w) {float elements[3][3] = {v.Matrixed(), u.Matrixed(), w.Matrixed()};}
Matrix3D::Matrix3D(float xx, float yx, float zx,
                 float xy, float yy, float zy,
                 float xz, float yz, float zz)
{
    float elements[3][3] = {xx, yx, zx,
                            xy, yy, zy,
                            xz, yz, zz};
}

Matrix3D Matrix3D::operator*(Matrix3D m2)
{
    Matrix3D result;
    for(short j = 0; j < 3; j++)
    {
        for(short k = 0; k < 3; k++)
        {
            float sum = 0.0f;
            for(short i = 0; i < 3; i++) sum += elements[j][i] * m2.elements[i][k];
            result.elements[j][k] = sum;
        }
    }
    return result;
}

Matrix3D Matrix3D::rotateX(float phi)
{
    const float sinPhi = sin(phi);
    const float cosPhi = cos(phi);
    return
    {
        1.0f, 0.0f,   0.0f,
        0.0f, cosPhi, sinPhi,
        0.0f,-sinPhi, cosPhi
    };
}
Matrix3D Matrix3D::rotateY(float theta)
{
    const float sinTheta = sin(theta);
    const float cosTheta = cos(theta);
    return
    {
         cosTheta, 0.0f,-sinTheta,
         0.0f,     1.0f, 0.0f,
         sinTheta, 0.0f, cosTheta
    };
}
Matrix3D Matrix3D::rotateZ(float psi)
{
    const float sinPsi = sin(psi);
    const float cosPsi = cos(psi);
    return
    {
        cosPsi,  sinPsi, 0.0f,
        -sinPsi, cosPsi, 0.0f,
        0.0f,    0.0f,   1.0f
    };
}

Matrix3D::~Matrix3D(){}

Vector3D operator*(const Vector3D& v, const Matrix3D& m)
{
    return
    {
        v.getX() * m.elements[0][0] + v.getY() * m.elements[1][0] + v.getZ() * m.elements[2][0],
        v.getX() * m.elements[0][1] + v.getY() * m.elements[1][1] + v.getZ() * m.elements[2][1],
        v.getX() * m.elements[0][2] + v.getY() * m.elements[1][2] + v.getZ() * m.elements[2][2]
    };
}

#endif

What I took out from the hpp and put inside the Matrix3D file:

Matrix3D::Matrix3D(){float elements[3][3] = {{1.0f,0.0f,0.0f}, {0.0f,1.0f,0.0f}, {0.0f,0.0f,1.0f}};}
Matrix3D::Matrix3D(Vector3D u, Vector3D v, Vector3D w) {float elements[3][3] = {v.Matrixed(), u.Matrixed(), w.Matrixed()};}
Matrix3D::Matrix3D(float xx, float yx, float zx,
                 float xy, float yy, float zy,
                 float xz, float yz, float zz)
{
    float elements[3][3] = {xx, yx, zx,
                            xy, yy, zy,
                            xz, yz, zz};
}

Matrix3D Matrix3D::operator*(Matrix3D m2)
{
    Matrix3D result;
    for(short j = 0; j < 3; j++)
    {
        for(short k = 0; k < 3; k++)
        {
            float sum = 0.0f;
            for(short i = 0; i < 3; i++) sum += elements[j][i] * m2.elements[i][k];
            result.elements[j][k] = sum;
        }
    }
    return result;
}

Matrix3D Matrix3D::rotateX(float phi)
{
    const float sinPhi = sin(phi);
    const float cosPhi = cos(phi);
    return
    {
        1.0f, 0.0f,   0.0f,
        0.0f, cosPhi, sinPhi,
        0.0f,-sinPhi, cosPhi
    };
}
Matrix3D Matrix3D::rotateY(float theta)
{
    const float sinTheta = sin(theta);
    const float cosTheta = cos(theta);
    return
    {
         cosTheta, 0.0f,-sinTheta,
         0.0f,     1.0f, 0.0f,
         sinTheta, 0.0f, cosTheta
    };
}
Matrix3D Matrix3D::rotateZ(float psi)
{
    const float sinPsi = sin(psi);
    const float cosPsi = cos(psi);
    return
    {
        cosPsi,  sinPsi, 0.0f,
        -sinPsi, cosPsi, 0.0f,
        0.0f,    0.0f,   1.0f
    };
}

Matrix3D::~Matrix3D(){}

Edit: I now have to go through my code to see what I'm doing wrong because I'm getting a lot fewer cygwin errors with $<, but now they're along the lines of:

/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: 3DMatrix.o:3DMatrix.cpp:(.text+0x29): undefined reference to `Vector3D::getX() const'
3DMatrix.o:3DMatrix.cpp:(.text+0x29): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `Vector3D::getX() const'
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: 3DMatrix.o:3DMatrix.cpp:(.text+0x225): undefined reference to `Vector3D::Matrixed()'
3DMatrix.o:3DMatrix.cpp:(.text+0x225): additional relocation overflows omitted from the output
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: /usr/lib/gcc/x86_64-pc-cygwin/10/../../../../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.1.7-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'

Though that changes back to the regular multiple definition error if I use $^ in the header file, so I think the way forward is to use $<. Though then again, there's also a bunch of new stuff in the cygwin errors for $^ such as

/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: main.o:main.cpp:(.text+0xa03): undefined reference to `stbi_write_png'
main.o:main.cpp:(.text+0xa03): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `stbi_write_png'
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: main.o:main.cpp:(.xdata+0x28): undefined reference to `__gxx_personality_seh0'
main.o:main.cpp:(.xdata+0x28): relocation truncated to fit: rva32 against undefined symbol `__gxx_personality_seh0'
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: main.o:main.cpp:(.text$_ZNSt20__uninitialized_copyILb0EE13__uninit_copyISt13move_iteratorIPSt10unique_ptrI5ShapeSt14default_deleteIS4_EEES8_EET0_T_SB_SA_[_ZNSt20__uninitialized_copyILb0EE13__uninit_copyISt13move_iteratorIPSt10unique_ptrI5ShapeSt14default_deleteIS4_EEES8_EET0_T_SB_SA_]+0x90): undefined reference to `__cxa_end_catch'
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: OBB.o:OBB.cpp:(.rdata$_ZTI3OBB[_ZTI3OBB]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'

Replace

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -c -o $@ $^

with

$(NAME): $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $^

The -c option is wrong (and is what is preventing linking).

You say that removing -c gives a bunch of cygwin errors. Could you share those errors? Just because you get more errors doesn't mean that removing -c is the wrong thing to do.

UPDATE

Well the error list proves that linking is now happening, which is progress. Unfortunately the new errors are caused by problems in your code. Since I can't see the code I can't really tell you how to fix them.

Putting non-inlined function definitions in header files would be one way to cause that kind of error. So would using #include on source files. Other possibilities exist as well.

MORE UPDATES

I have

#ifndef #define

#endif

in all the hpp files, so I can't say why it's complaining about multiple definitions.

This is a common miunderstanding. Include guards are not a cure for multiple definition errors.

Look at your header files, do they contain non-inlined function definitions? If so then fix that, either by making the function definition inline, or by moving the function definition out of the header file.

UPDATE UPDATE

Exactly as I said, your header files are stuffed full of non-inlined function definitions. Fix them.

And to repeat, include guards have nothing at all to do with this issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM