0

having tried to compile this source code the linker cannot find and link AntTweakBar library with the project. I tried to link it like GLEW, glfw and glm but none worked. It seems that I didn't include something in the CMakeList.txt file to properly introduce the package to the compiler if you have any knowledge please give me an straight forward way to handle this any help appreciated

main.cpp

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
 
// Include GLEW
#include <GL/glew.h>
 
// Include GLFW
#include <GLFW/glfw3.h>
GLFWwindow* window;

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/norm.hpp>
using namespace glm;
 
// Include AntTweakBar
#include <AntTweakBar.h>
 
 
#include <common/shader.hpp>
#include <common/texture.hpp>
#include <common/controls.hpp>
#include <common/objloader.hpp>
#include <common/vboindexer.hpp>
#include <common/quaternion_utils.hpp> // See quaternion_utils.cpp for RotationBetweenVectors, LookAt and RotateTowards

vec3 gPosition1(-1.5f, 0.0f, 0.0f);
vec3 gOrientation1;
 
vec3 gPosition2( 1.5f, 0.0f, 0.0f);
quat gOrientation2;
 
bool gLookAtOther = true;

 
int main( void )
{
 
    // Initialise GLFW
    if( !glfwInit() )
    {
        fprintf( stderr, "Failed to initialize GLFW\n" );
        getchar();
        return -1;
    }
 
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 
    // Open a window and create its OpenGL context
    window = glfwCreateWindow( 1024, 768, "Tutorial 17 - Rotations", NULL, NULL);
    if( window == NULL ){
        fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
        getchar();
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
        fprintf(stderr, "Failed to initialize GLEW\n");
        getchar();
        glfwTerminate();
        return -1;
    }
 
    // Initialize the GUI
    TwInit(TW_OPENGL_CORE, NULL);
    TwWindowSize(1024, 768);
    TwBar * EulerGUI = TwNewBar("Euler settings");
    TwBar * QuaternionGUI = TwNewBar("Quaternion settings");
    TwSetParam(EulerGUI, NULL, "refresh", TW_PARAM_CSTRING, 1, "0.1");
    TwSetParam(QuaternionGUI, NULL, "position", TW_PARAM_CSTRING, 1, "808 16");

    TwAddVarRW(EulerGUI, "Euler X", TW_TYPE_FLOAT, &gOrientation1.x, "step=0.01");
    TwAddVarRW(EulerGUI, "Euler Y", TW_TYPE_FLOAT, &gOrientation1.y, "step=0.01");
    TwAddVarRW(EulerGUI, "Euler Z", TW_TYPE_FLOAT, &gOrientation1.z, "step=0.01");
    TwAddVarRW(EulerGUI, "Pos X"  , TW_TYPE_FLOAT, &gPosition1.x, "step=0.1");
    TwAddVarRW(EulerGUI, "Pos Y"  , TW_TYPE_FLOAT, &gPosition1.y, "step=0.1");
    TwAddVarRW(EulerGUI, "Pos Z"  , TW_TYPE_FLOAT, &gPosition1.z, "step=0.1");
 
    TwAddVarRW(QuaternionGUI, "Quaternion", TW_TYPE_QUAT4F, &gOrientation2, "showval=true open=true ");
    TwAddVarRW(QuaternionGUI, "Use LookAt", TW_TYPE_BOOL8 , &gLookAtOther, "help='Look at the other monkey ?'");
 
    // Set GLFW event callbacks. I removed glfwSetWindowSizeCallback for conciseness
    glfwSetMouseButtonCallback(window, (GLFWmousebuttonfun)TwEventMouseButtonGLFW); // - Directly redirect GLFW mouse button events to AntTweakBar
    glfwSetCursorPosCallback(window, (GLFWcursorposfun)TwEventMousePosGLFW);          // - Directly redirect GLFW mouse position events to AntTweakBar
    glfwSetScrollCallback(window, (GLFWscrollfun)TwEventMouseWheelGLFW);    // - Directly redirect GLFW mouse wheel events to AntTweakBar
    glfwSetKeyCallback(window, (GLFWkeyfun)TwEventKeyGLFW);                         // - Directly redirect GLFW key events to AntTweakBar
    glfwSetCharCallback(window, (GLFWcharfun)TwEventCharGLFW);                      // - Directly redirect GLFW char events to AntTweakBar
 
 
    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
    // Hide the mouse and enable unlimited mouvement
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    
    // Set the mouse at the center of the screen
    glfwPollEvents();
    glfwSetCursorPos(window, 1024/2, 768/2);
 
    // Dark blue background
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
 
    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    // Accept fragment if it closer to the camera than the former one
    glDepthFunc(GL_LESS); 
 
    // Cull triangles which normal is not towards the camera
    glEnable(GL_CULL_FACE);
 
    // Create and compile our GLSL program from the shaders
    GLuint programID = LoadShaders( "StandardShading.vertexshader", "StandardShading.fragmentshader" );
 
    // Get a handle for our "MVP" uniform
    GLuint MatrixID = glGetUniformLocation(programID, "MVP");
    GLuint ViewMatrixID = glGetUniformLocation(programID, "V");
    GLuint ModelMatrixID = glGetUniformLocation(programID, "M");
 
    // Get a handle for our buffers
    GLuint vertexPosition_modelspaceID = glGetAttribLocation(programID, "vertexPosition_modelspace");
    GLuint vertexUVID = glGetAttribLocation(programID, "vertexUV");
    GLuint vertexNormal_modelspaceID = glGetAttribLocation(programID, "vertexNormal_modelspace");
 
    // Load the texture
    GLuint Texture = loadDDS("uvmap.DDS");
    
    // Get a handle for our "myTextureSampler" uniform
    GLuint TextureID  = glGetUniformLocation(programID, "myTextureSampler");
 
    // Read our .obj file
    std::vector<glm::vec3> vertices;
    std::vector<glm::vec2> uvs;
    std::vector<glm::vec3> normals;
    bool res = loadOBJ("suzanne.obj", vertices, uvs, normals);
 
    std::vector<unsigned short> indices;
    std::vector<glm::vec3> indexed_vertices;
    std::vector<glm::vec2> indexed_uvs;
    std::vector<glm::vec3> indexed_normals;
    indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals);
 
    // Load it into a VBO
 
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);
 
    GLuint uvbuffer;
    glGenBuffers(1, &uvbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW);
 
    GLuint normalbuffer;
    glGenBuffers(1, &normalbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);
 
    // Generate a buffer for the indices as well
    GLuint elementbuffer;
    glGenBuffers(1, &elementbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0] , GL_STATIC_DRAW);
 
    // Get a handle for our "LightPosition" uniform
    glUseProgram(programID);
    GLuint LightID = glGetUniformLocation(programID, "LightPosition_worldspace");
 
    // For speed computation
    double lastTime = glfwGetTime();
    double lastFrameTime = lastTime;
    int nbFrames = 0;
 
    do{
 
        // Measure speed
        double currentTime = glfwGetTime();
        float deltaTime = (float)(currentTime - lastFrameTime); 
        lastFrameTime = currentTime;
        nbFrames++;
        if ( currentTime - lastTime >= 1.0 ){ // If last prinf() was more than 1sec ago
            // printf and reset
            printf("%f ms/frame\n", 1000.0/double(nbFrames));
            nbFrames = 0;
            lastTime += 1.0;
        }
 
        // Clear the screen
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        // Use our shader
        glUseProgram(programID);
 
        glm::mat4 ProjectionMatrix = glm::perspective(glm::radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);
        glm::mat4 ViewMatrix = glm::lookAt(
            glm::vec3( 0, 0, 7 ), // Camera is here
            glm::vec3( 0, 0, 0 ), // and looks here
            glm::vec3( 0, 1, 0 )  // Head is up (set to 0,-1,0 to look upside-down)
        );
 
        // Bind our texture in Texture Unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, Texture);
        // Set our "myTextureSampler" sampler to use Texture Unit 0
        glUniform1i(TextureID, 0);
 
        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
            vertexPosition_modelspaceID,  // The attribute we want to configure
            3,                            // size
            GL_FLOAT,                     // type
            GL_FALSE,                     // normalized?
            0,                            // stride
            (void*)0                      // array buffer offset
        );
 
        // 2nd attribute buffer : UVs
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
        glVertexAttribPointer(
            vertexUVID,                   // The attribute we want to configure
            2,                            // size : U+V => 2
            GL_FLOAT,                     // type
            GL_FALSE,                     // normalized?
            0,                            // stride
            (void*)0                      // array buffer offset
        );
 
        // 3rd attribute buffer : normals
        glEnableVertexAttribArray(2);
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glVertexAttribPointer(
            vertexNormal_modelspaceID,    // The attribute we want to configure
            3,                            // size
            GL_FLOAT,                     // type
            GL_FALSE,                     // normalized?
            0,                            // stride
            (void*)0                      // array buffer offset
        );
 
        // Index buffer
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
 
        glm::vec3 lightPos = glm::vec3(4,4,4);
        glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
 
        { // Euler
 
            // As an example, rotate arount the vertical axis at 180�/sec
            gOrientation1.y += 3.14159f/2.0f * deltaTime;
 
            // Build the model matrix
            glm::mat4 RotationMatrix = eulerAngleYXZ(gOrientation1.y, gOrientation1.x, gOrientation1.z);
            glm::mat4 TranslationMatrix = translate(mat4(), gPosition1); // A bit to the left
            glm::mat4 ScalingMatrix = scale(mat4(), vec3(1.0f, 1.0f, 1.0f));
            glm::mat4 ModelMatrix = TranslationMatrix * RotationMatrix * ScalingMatrix;
 
            glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
 
            // Send our transformation to the currently bound shader, 
            // in the "MVP" uniform
            glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
            glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
            glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
 
 
 
            // Draw the triangles !
            glDrawElements(
                GL_TRIANGLES,      // mode
                indices.size(),    // count
                GL_UNSIGNED_SHORT,   // type
                (void*)0           // element array buffer offset
            );
 
        }
        { // Quaternion
 
            // It the box is checked...
            if (gLookAtOther){
                vec3 desiredDir = gPosition1-gPosition2;
                vec3 desiredUp = vec3(0.0f, 1.0f, 0.0f); // +Y
 
                // Compute the desired orientation
                quat targetOrientation = normalize(LookAt(desiredDir, desiredUp));
 
                // And interpolate
                gOrientation2 = RotateTowards(gOrientation2, targetOrientation, 1.0f*deltaTime);
            }
 
            glm::mat4 RotationMatrix = mat4_cast(gOrientation2);
            glm::mat4 TranslationMatrix = translate(mat4(), gPosition2); // A bit to the right
            glm::mat4 ScalingMatrix = scale(mat4(), vec3(1.0f, 1.0f, 1.0f));
            glm::mat4 ModelMatrix = TranslationMatrix * RotationMatrix * ScalingMatrix;
 
            glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
 
            // Send our transformation to the currently bound shader, 
            // in the "MVP" uniform
            glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
            glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
            glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
 
 
            // Draw the triangles !
            glDrawElements(
                GL_TRIANGLES,      // mode
                indices.size(),    // count
                GL_UNSIGNED_SHORT,   // type
                (void*)0           // element array buffer offset
            );
        }
 
        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);
        glDisableVertexAttribArray(2);
 
        // Draw GUI
        TwDraw();
 
        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();
 
    } // Check if the ESC key was pressed or the window was closed
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
           glfwWindowShouldClose(window) == 0 );
 
    // Cleanup VBO and shader
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteBuffers(1, &uvbuffer);
    glDeleteBuffers(1, &normalbuffer);
    glDeleteBuffers(1, &elementbuffer);
    glDeleteProgram(programID);
    glDeleteTextures(1, &Texture);
 
    // Close GUI and OpenGL window, and terminate GLFW
    TwTerminate();
    glfwTerminate();
 
    return 0;
}
 

CMakeList.txt

cmake_minimum_required(VERSION 3.20)
project(graphics)

set(CMAKE_CXX_STANDARD 20)

add_executable(graphics main.cpp common/shader.hpp common/shader.cpp common/shader.hpp)
file(GLOB common CONFIGURE_DEPENDS "*.hpp" "*.cpp")

find_package(glfw3 3.3.7 REQUIRED)
find_package(glm REQUIRED)
find_package(GLEW 2.2.0 REQUIRED)
find_package(OpenGL REQUIRED)
#find_path(AntTweakBar AntTweakBar.h)

target_include_directories(graphics PUBLIC ${OPENGL_INCLUDE_DIR})

target_link_libraries(graphics "-framework Cocoa")
target_link_libraries(graphics "-framework OpenGL")
target_link_libraries(graphics "-framework IOKit")
target_link_libraries(graphics glfw ${OPENGL_gl_LIBRARY})
target_link_libraries(graphics GLEW::GLEW)
target_link_libraries(graphics ${GLM_LIBRARY})
#target_link_libraries(graphics ${ANTTWEAKBAR_LIBRARY})

build

====================[ Build | graphics | Debug ]================================
/Applications/CLion.app/Contents/bin/cmake/mac/bin/cmake --build /Users/clonerplus/Desktop/graphics/cmake-build-debug --target graphics -- -j 6
Scanning dependencies of target graphics
[ 33%] Building CXX object CMakeFiles/graphics.dir/main.cpp.o
[ 66%] Linking CXX executable graphics
Undefined symbols for architecture arm64:
  "_TwAddVarRW", referenced from:
      _main in main.cpp.o
  "_TwDraw", referenced from:
      _main in main.cpp.o
  "_TwEventCharGLFW", referenced from:
      _main in main.cpp.o
  "_TwEventKeyGLFW", referenced from:
      _main in main.cpp.o
  "_TwEventMouseButtonGLFW", referenced from:
      _main in main.cpp.o
  "_TwInit", referenced from:
      _main in main.cpp.o
  "_TwMouseMotion", referenced from:
      _main in main.cpp.o
  "_TwMouseWheel", referenced from:
      _main in main.cpp.o
  "_TwNewBar", referenced from:
      _main in main.cpp.o
  "_TwSetParam", referenced from:
      _main in main.cpp.o
  "_TwTerminate", referenced from:
      _main in main.cpp.o
  "_TwWindowSize", referenced from:
      _main in main.cpp.o
  "RotateTowards(glm::qua<float, (glm::qualifier)0>, glm::qua<float, (glm::qualifier)0>, float)", referenced from:
      _main in main.cpp.o
  "LookAt(glm::vec<3, float, (glm::qualifier)0>, glm::vec<3, float, (glm::qualifier)0>)", referenced from:
      _main in main.cpp.o
  "loadDDS(char const*)", referenced from:
      _main in main.cpp.o
  "loadOBJ(char const*, std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<2, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<2, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&)", referenced from:
      _main in main.cpp.o
  "indexVBO(std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<2, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<2, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&, std::__1::vector<unsigned short, std::__1::allocator<unsigned short> >&, std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<2, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<2, float, (glm::qualifier)0> > >&, std::__1::vector<glm::vec<3, float, (glm::qualifier)0>, std::__1::allocator<glm::vec<3, float, (glm::qualifier)0> > >&)", referenced from:
      _main in main.cpp.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[3]: *** [graphics] Error 1
make[2]: *** [CMakeFiles/graphics.dir/all] Error 2
make[1]: *** [CMakeFiles/graphics.dir/rule] Error 2
make: *** [graphics] Error 2

also I'm using m1 mac and build the AntTweakBar from source from Homebrew

Rabbid76
  • 177,135
  • 25
  • 101
  • 146
cloner
  • 1
  • 1
  • 1
    Please, do not ask the same question again just because it was closed. In your previous question I gave you a link to the [question](https://stackoverflow.com/questions/8774593/cmake-link-to-external-library) on Stack Overflow about linking libraries. Have you read it? Have you tried to apply any of its answers to your case, for link with `AntTweakBar` library? – Tsyvarev May 26 '22 at 18:04

0 Answers0