cmake文件来构建opengl项目

1cklez4t  于 2023-03-30  发布在  其他
关注(0)|答案(2)|浏览(170)

我曾经使用Windows使用Visual Studio制作OpenGL项目,设置依赖关系相对容易,现在我在Ubuntu 20. 4中尝试一些东西,并使用Cmake来构建,存在构建错误。
我的项目结构-

--------path to project dir|
                           |---external_dep|
                           |               |----include|
                           |               |           |----glad|
                           |               |           |        |---related headers
                           |               |           |
                           |               |           |----GLFW|
                           |               |           |        |---related headers
                           |               |           |----KHR|
                           |               |           |       |----related headers
                           |               |           |
                           |               |           |----GLM|
                           |               |                   |----related headers
                           |               |
                           |               |----lib| 
                           |               |       |------libglfw3.a
                           |               |
                           |----resources|
                           |             |----vertex.glsl
                           |             |----fragment.glsl
                           |
                           |----src|
                           |       |----main.cpp
                           |       |----shaderclass.h
                           |       |----shaderclass.cpp
                           |       |----glad.c
                           |
                           |----CMakeLists.txt

现在我找到了几个教程,但是他们使用ubuntu apt包和一个简单的命令find_package()来完成这项工作,但是我想沿着所有的依赖项来构建我的程序。
我的CMakeLists.txt

cmake_minimum_required(VERSION 3.14)
project(triangle)
set(CMAKE_BUILD_TYPE "Release")

find_package(OpenGL REQUIRED)

include_directories(${CMAKE_SOURCE_DIR}/external_dep/include)
link_directories(${CMAKE_SOURCE_DIR}/external_dep/lib)

add_executable(triangle src/main.cpp src/glad.c src/shaderCreation.h src/shaderCreation.cpp)

target_link_libraries(triangle PUBLIC glfw3 ${CMAKE_DL_LIBS} m OpenGL::GL X11)

这给出了错误。

[build] /usr/bin/ld: /home/alvi95/Personal/code/TutOpenGL/2.triangle/example1/external_dep/lib/libglfw3.a(posix_thread.c.o): in function `_glfwPlatformCreateTls':
[build] posix_thread.c:(.text+0x4a): undefined reference to `pthread_key_create'
[build] /usr/bin/ld: /home/alvi95/Personal/code/TutOpenGL/2.triangle/example1/external_dep/lib/libglfw3.a(posix_thread.c.o): in function `_glfwPlatformDestroyTls':
[build] posix_thread.c:(.text+0xa4): undefined reference to `pthread_key_delete'
[build] /usr/bin/ld: /home/alvi95/Personal/code/TutOpenGL/2.triangle/example1/external_dep/lib/libglfw3.a(posix_thread.c.o): in function `_glfwPlatformGetTls':
[build] posix_thread.c:(.text+0x105): undefined reference to `pthread_getspecific'
[build] /usr/bin/ld: /home/alvi95/Personal/code/TutOpenGL/2.triangle/example1/external_dep/lib/libglfw3.a(posix_thread.c.o): in function `_glfwPlatformSetTls':
[build] posix_thread.c:(.text+0x15a): undefined reference to `pthread_setspecific'
[build] collect2: error: ld returned 1 exit status
[build] ninja: build stopped: subcommand failed.
[proc] The command: /usr/local/bin/cmake --build /home/alvi95/Personal/code/TutOpenGL/2.triangle/example1/build --config Release --target all -- exited with code: 1
[build] Build finished with exit code 1

如何正确的编写cmake文件?如何在构建过程中链接着色器文件?

wgmfuz8q

wgmfuz8q1#

我已经找到了让程序编译和运行的方法,我不是程序员,而是一个想要可视化物理模拟的机械工程师。

cmake_minimum_required(VERSION 3.14)
project(triangle)
set(CMAKE_BUILD_TYPE "Release")

find_package(OpenGL REQUIRED)

include_directories(${CMAKE_SOURCE_DIR}/external_dep/include)
link_directories(${CMAKE_SOURCE_DIR}/external_dep/lib)

add_executable(triangle src/main.cpp src/glad.c src/shaderClass.h src/shaderClass.cpp)

add_custom_target(
    copy-shaders ALL
    COMMENT "Copying shaders"
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_CURRENT_SOURCE_DIR}/resource ${CMAKE_BINARY_DIR}/resource)

add_dependencies(${PROJECT_NAME} copy-shaders)

target_link_libraries(triangle PUBLIC glfw3 OpenGL::GL X11 Xi Xrandr Xxf86vm Xinerama Xcursor rt m ${CMAKE_DL_LIBS} -pthread)

文件结构与上面给出的相同。
我的main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "shaderCreation.h"

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(800, 600, "Triangle", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    Shader shader1("resource/vertex.glsl", "resource/fragment.glsl");

    GLfloat vertices[] = {
       -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };

    GLuint vbo, vao;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &vbo);
    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window))
    {
        processInput(window);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        shader1.use();
        glBindVertexArray(vao);
        glDrawArrays(GL_TRIANGLES,0,3);

        glfwPollEvents();
        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;    

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

void processInput(GLFWwindow *window)
{
    if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

shaderClass.h

#ifndef SHADERCLASS_H
#define SHADERCLASS_H

#include<glad/glad.h>
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<cerrno>
#include <unistd.h>

namespace pathhelper
{
    std::string getApplicationPathAndName();
    std::string getApplicationPath();
}

std::string get_file_contents(const char* filename);

class Shader
{
public:

    GLuint ID;

    Shader(std::string vertexFile, std::string fragmentFile);

    void setBool(const std::string &name, bool value) const;
    void setInt(const std::string &name, int value) const;
    void setFloat(const std::string &name, float value) const;

    void use();

    void Delete();
};
#endif

shaderClass.cpp

#include "shaderCreation.h"

std::string pathhelper::getApplicationPathAndName()

{
    std::string fullPath;
    char pathBuffer[1024];
    ssize_t len = readlink("/proc/self/exe", pathBuffer, sizeof(pathBuffer)-1);
    if (len != -1) {
        pathBuffer[len] = '\0';
        fullPath = pathBuffer;
    } else {
        throw std::runtime_error("Unable to ascertain application path");
    }
    return fullPath;
}

std::string pathhelper::getApplicationPath()
{
    std::string fullPath = getApplicationPathAndName();
    return fullPath.substr(0, fullPath.find_last_of('/'));
}

std::string get_file_contents(const char* filename)
{
    std::ifstream in(filename, std::ios::binary);
    if (in)
    {
        std::string contents;
        in.seekg(0, std::ios::end);
        contents.resize(in.tellg());
        in.seekg(0, std::ios::beg);
        in.read(&contents[0], contents.size());
        in.close();
        return(contents);
    }
    throw(errno);
}

Shader::Shader(std::string vertexFile, std::string fragmentFile)
{
    int success;
    char infoLog[512];

    std::string appPath = pathhelper::getApplicationPath();
    std::string vertexPath = appPath + "/" + vertexFile;
    std::string fragmentPath = appPath + "/" + fragmentFile;

    std::string vertexCode = get_file_contents(vertexPath.c_str());
    std::string fragmentCode = get_file_contents(fragmentPath.c_str());

    const char* vertexSource = vertexCode.c_str();
    const char* fragmentSource = fragmentCode.c_str();

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexSource, NULL);
    glCompileShader(vertexShader);
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }


    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
    glCompileShader(fragmentShader);

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }


    ID = glCreateProgram();

    glAttachShader(ID, vertexShader);
    glAttachShader(ID, fragmentShader);

    glLinkProgram(ID);

    glGetProgramiv(ID, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(ID, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

void Shader::setBool(const std::string &name, bool value) const
{         
    glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); 
}

void Shader::setInt(const std::string &name, int value) const
{ 
    glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 
}

void Shader::setFloat(const std::string &name, float value) const
{ 
    glUniform1f(glGetUniformLocation(ID, name.c_str()), value); 
}

void Shader::use()
{
    glUseProgram(ID);
}

void Shader::Delete()
{
    glDeleteProgram(ID);
}
hc2pp10m

hc2pp10m2#

编写CMakeLists.txt文件取决于具体的项目和构建需求,但这里有一些通用指南:
使用cmake_minimum_required()在文件顶部设置所需的CMake最低版本。
使用project()创建项目名称。
使用set()和add_compile_options()设置任何必要的项目范围的选项或设置,例如构建类型、C++标准、编译器标志等。
使用add_subdirectory()添加包含其他CMakeLists.txt文件的任何子目录。
使用find_package()包含项目所需的任何外部库,或使用link_directories()手动链接到它们的位置。
要构建可执行目标,请使用add_executable()并列出必要的源文件。
要构建库目标,请使用add_library()并列出必要的源文件。
使用target_link_libraries()将所有必要的库链接到目标。
对于在构建过程中链接着色器文件,您可以使用configure_file()或add_custom_command()根据需要复制或预处理它们。然后像链接任何其他源文件一样链接处理后的文件。
下面是一个构建可执行目标的示例CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)

项目(MyProject)
设置(CMAKE_CXX_标准11)
add_executable(MyExecutable main.cpp shader.vert shader.frag)

链接GLFW和GLEW库

查找程序包(需要GLFW)查找程序包(需要GLEW)目标链接库(我的可执行文件GLFW::GLFW GLEW::GLEW)
在本例中,set()命令用于将C++标准设置为11。add_executable()命令创建MyExecutable目标,并指定它由main.cpp、shader.vert和shader.frag源文件组成。find_package()命令用于定位GLFW和GLEW库,target_link_libraries()用于将它们链接到可执行目标。

相关问题