mosra / magnum

Lightweight and modular C++11 graphics middleware for games and data visualization
https://magnum.graphics/
Other
4.74k stars 439 forks source link

Failing to link Magnum::Math? #609

Closed Reticulatas closed 1 year ago

Reticulatas commented 1 year ago

This might be a misunderstanding of CMake on my part. Compiling a simple project is giving me

F:\Projects\Forlorn\src\game\Actor.h(16,10): error C2079: 'Actor::Position' uses undefined class 'Magnum::Math::Vector3
<Magnum::Float>' [F:\Projects\Forlorn\build\src\Forlorn.vcxproj]

After following the setup guide, I added a new file to the bootstrap:

#pragma once

#include <Magnum/Magnum.h>
#include <Magnum/Types.h>
#include <Magnum/Math/Math.h>

using namespace Magnum;

class Actor
{
private:
    Vector3 Position;
};

Here is my CMakeLists:

project(Forlorn CXX)

# Add module path in case this is project root
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
    set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../../modules/" ${CMAKE_MODULE_PATH})
endif()

find_package(Corrade REQUIRED Main)
find_package(Magnum REQUIRED 
    GL 
    Shaders
    Sdl2Application
)

set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)

add_executable(Forlorn WIN32
    MyApplication.cpp
    game/Actor.cpp
    game/Actor.h
)

target_include_directories(Forlorn PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_BINARY_DIR}
)

target_link_libraries(Forlorn PRIVATE
    Corrade::Main
    Magnum::Application
    Magnum::GL
    Magnum::Magnum
    Magnum::Shaders
    Magnum::Primitives
    Magnum::SceneGraph
)

install(TARGETS Forlorn DESTINATION ${MAGNUM_BINARY_INSTALL_DIR})

# Make the executable a default target to build & run in Visual Studio
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_START

Building using VS0222 after running

cmake -DCMAKE_BUILD_TYPE=Debug ..

I can see the magnum lib being included in VS and there are no other errors- What is happening here? Tried Clean/Rebuild, remake CMake.

Reticulatas commented 1 year ago

I figured this out. I'm not sure why, but the build succeeds when I do: #include <Magnum/Platform/Sdl2Application.h> instead of #include <Magnum/Magnum.h>

mosra commented 1 year ago

Hi!

It's not because of CMake, it's because most Magnum types are forward-declared unless you explicitly include the header the type is defined in. Which is the case of <Magnum/Magnum.h> that contains mainly just forward declarations of essential types, and to get the definition of Vector3 you have to #include <Magnum/Math/Vector3.h>. To make it easier for you, each API in the docs explicitly lists what header to include to get the full definition.

It worked with <Magnum/Platform/Sdl2Application.h> only because that header actually needs the full definition of the vector and so it includes <Magnum/Math/Vector3.h> on its own.

I admit that this might feel unusual at first, as <SomeLibrary/SomeLibrary.h> usually pulls in all types defined by given library. (For example Bullet, Eigen or Unreal does exactly that.) The reason for Magnum having just forward declarations in those headers is to optimize compilation times, see this part of the documentation for more information.

Hope this helps! :)

Reticulatas commented 1 year ago

Thanks for the explanation, makes sense upon reading that doc!

Maybe a footnote in the example docs about includes linking to that page would be good?