Closed kovrov closed 2 years ago
I hadn't had a chance to test this on a windows box. Only on linux (ubuntu) and osx.
That is quite cool, nice setup! If this is merged, it should probably also be referenced by the tutorial as a possible example of how to set up Vulkan projects. I can try to test it on Windows sometime this week.
I just realized I was calling glslangvalidator
with --target-env vulkan1.2
. Fixed to match the value used in VkApplicationInfo::apiVersion
.
I get the following errors when trying to build on Arch Linux:
$ cmake .
CMake Error at CMakeLists.txt:46 (add_executable):
Target "27_model_loading" links to target "glm::glm" but the target was not
found. Perhaps a find_package() call is missing for an IMPORTED target, or
an ALIAS target is missing?
Call Stack (most recent call first):
CMakeLists.txt:156 (add_chapter)
...
$ cmake --build .
[ 1%] Generating 27_model_loading/shaders
[ 2%] Compiling Shaders
[ 2%] Built target 27_model_loading_shader
[ 3%] Building CXX object CMakeFiles/27_model_loading.dir/27_model_loading.cpp.o
[ 4%] Linking CXX executable 27_model_loading/27_model_loading
/usr/bin/ld: cannot find -lglm::glm
/usr/bin/ld: cannot find -ltinyobjloader::tinyobjloader
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/27_model_loading.dir/build.make:106: 27_model_loading/27_model_loading] Error 1
make[1]: *** [CMakeFiles/Makefile2:214: CMakeFiles/27_model_loading.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
When I change all glm::glm
references to just glm
and tinyobjloader::tinyobjloader
to just tinyobjloader
everything works just fine. Do you know what might be up with that? This is with cmake version 3.21.1.
This is interesting, looks like a "downstream" issue. Different distros may provide and maintain its own cmake configs for the dev packages.
On my ubuntu box (20.04) the glm package (0.9.9.7) is installed from ubuntu repo. The library is declared as "glm::glm" (in /usr/lib/cmake/glm/glmConfig.cmake):
add_library(glm::glm INTERFACE IMPORTED)
tinyobjloader
is in similar situation - /usr/lib/x86_64-linux-gnu/cmake/tinyobjloader/tinyobjloader-targets.cmake (although libtinyobjloader-dev is not from 20.04, but rather was backported from 20.10):
add_library(tinyobjloader::tinyobjloader SHARED IMPORTED)
What's interesting is that on my macbook, the packages (installed via homebrew formulas) has the same target names. I was hoping this is universal naming convention.
Since glm is a header-only library, the only reason to "findpackage" and "link" it to the executable is to configure include paths (imported targets usually has INTERFACE_INCLUDE_DIRECTORIES
property).
tinyobjloader on the other side, is an actual library we need to link against. And as far as I remember on mac, simply linking via -ltinyobjloader
was failing (likely because it is not located on standard library paths).
Edit:
For what it worth, the glm manual specifies its cmake module as "glm::glm" (https://github.com/g-truc/glm/blob/master/manual.md#-15-finding-glm-with-cmake):
find_package(glm REQUIRED)
target_link_libraries(<your executable> glm::glm)
@Overv what are the versions of installed tinyobjloader
and glm
dev packages?
The versions I have installed are:
glm
: 0.9.9.8-1tinyobjloader
: The header says 1.4.0, although that release/tag doesn't seem to exist in the repo. Anyhow, the library is installed from a commit on Dec 15 2018.I'm not sure why this is happening since I know very little about cmake myself.
The line you mention (add_library
) is not in my glmConfig.cmake
, but the following line is in my glmTargets.cmake
:
add_library(glm INTERFACE IMPORTED)
I'm not sure why they are using a different name in the Arch Linux package.
Update: I've created a bug report to ask about this: https://bugs.archlinux.org/task/71987
Weird, since glm release 0.9.9.8 cmake target should be glm::glm. On the other hand your tinyobjloader library is indeed old and don't have latest cmake changes.
Anyway. This is not important. We know that correct targets are glm::glm and tinyobjloader::tinyobjloader. And this specific problem is in dev environment. Possible solutions are:
Keep this change as is and rely on users to "correct" their environment if needed.
Add a workaround in our cmake project, e.g:
if (NOT TARGET tinyobjloader::tinyobjloader) add_library(tinyobjloader::tinyobjloader ALIAS tinyobjloader) endif () if (NOT TARGET glm::glm) add_library(glm::glm ALIAS glm) endif ()
More importantly, I'd like to see if there are any issues on windows.
I just tested it on Windows and ran into a few small issues:
CMake Error at CMakeLists.txt:5 (find_package):
By not providing "Findglfw3.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "glfw3", but
CMake did not find one.
Could not find a package configuration file provided by "glfw3" with any of
the following names:
glfw3Config.cmake
glfw3-config.cmake
Add the installation prefix of "glfw3" to CMAKE_PREFIX_PATH or set
"glfw3_DIR" to a directory containing one of the above files. If "glfw3"
provides a separate development package or SDK, be sure it has been
installed.
It looks like it couldn't automatically find glfw3
because it installs into a directory called GLFW
by default due to the project name being GLFW
rather than glfw3
. When I rename the install directory to glfw3
it works just fine. This is a known issue.
stb_image.h
by itself, which makes sense.CMake Error at CMakeLists.txt:17 (message):
stb_image.h not found
However, it did find both glm
and tinyobjloader
automatically without any issues.
After generating all of the projects I could build them just fine with Visual Studio 2017. However, the executables crash because they can't find glfw3.dll
. After manually copying glfw3.dll
to the directory containing the executable, it starts running but crashes with a runtime exception failed to open file!
because it cannot find the compiled shader shaders/vert.spv
.
I fixed this by changing the "Working Directory" in the "Debugging" section of the project settings from $(ProjectDir)
to $(ProjectDir)$(ProjectName)
. This can be fixed in CMake by adding the following line to CMakeLists.txt in add_chapter
:
set_target_properties (${CHAPTER_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/${CHAPTER_NAME}")
I'm not sure what to do about the dll issue, but we should probably just recommend users to add glfw3.dll
to their path.
Thanks!
Where is stb_image.h
located on your windows box?
This statement is basically searches for stb_image.h in standard include locations (e.g. /usr/include, /usr/include/ARCH, /usr/ARCH/include, etc.) with additional subdirectory stb to check below each standard directory:
find_path (STB_INCLUDEDIR stb_image.h PATH_SUFFIXES stb)
In my case it is in /usr/include/stb/stb_image.h
Solution would be to set CMAKE_INCLUDE_PATH
override in visual studio project (equivalent of -DCMAKE_INCLUDE_PATH=/path/to/stb
command line argument).
I guess the runtime problem finding the dll is caused by changed location of the GLFW binary dir.
Try this - instead of manually renaming GLFW folder to glfw3, configure and build GLFW with CMAKE_INSTALL_PREFIX
set to C:/Program Files (x86)/glfw3
and then install. E.g.:
cmake -DCMAKE_INSTALL_PREFIX="C:/Program Files (x86)/glfw3" ../glfw
cmake --build .
cmake --install .
When CMAKE_INSTALL_PREFIX
not set, it going be something like c:/Program Files/${PROJECT_NAME}
by default, which sounds like your case.
Where is
stb_image.h
located on your windows box?
In ~/source/libs/stb-master
where ~
is my Windows home directory. To my knowledge there is no standard include location in Windows so I wouldn't know where else to put it.
Try this - instead of manually renaming GLFW folder to glfw3, configure and build GLFW with
CMAKE_INSTALL_PREFIX
set toC:/Program Files (x86)/glfw3
and then install. E.g.:
That didn't make a difference for me. I think that it'll only find glfw3.dll
automatically if it's either in the same directory as the executable or in the system path. It doesn't look like cmake is adding any directories (like C:/Program Files (x86)/glfw3
) to the system path as part of the install process.
With that said, we could avoid this situation by statically linking glfw3 on Windows.
On a sidenote, the issue with the glm target being named differently in Arch will be fixed soon.
Configuring with -DCMAKE_INCLUDE_PATH=~/source/libs/stb-master
argument (visual studio may have a gui to define cmake variables) should fix the failing check for stb_image.h.
Configuring with
-DCMAKE_INCLUDE_PATH=~/source/libs/stb-master
argument (visual studio may have a gui to define cmake variables) should fix the failing check for stb_image.h.
Alright, but then you might as well configure STB_INCLUDEDIR
directly.
Configuring with
-DCMAKE_INCLUDE_PATH=~/source/libs/stb-master
argument (visual studio may have a gui to define cmake variables) should fix the failing check for stb_image.h.Alright, but then you might as well configure
STB_INCLUDEDIR
directly.
STB_INCLUDEDIR
is meant to be set automatically on environments that either provides stb pkgconf file (e.g. ubuntu) or has the stb headers on standard locations.
Unfortunately upstream STB is not providing any config packages, because it is designed to be project-level drop-in headers.
If there is a well known windows development practice when it comes to 3rd party libraries locations, we could hard-code additional paths argument (called HINTS
) to find_path
invocation. Otherwise, there is nothing else I can think of but requiring user to setCMAKE_INCLUDE_PATH
(which was designed exactly for this purpose).
STB_INCLUDEDIR
is meant to be set automatically on environments that either provides stb pkgconf file (e.g. ubuntu) or has the stb headers on standard locations.
Right, but I don't think it's common to have all header files together in a single directory like with /usr/include
on Linux. That's why I figured that it made more sense to specify an include directory per library rather than to give CMake one global include path.
If there is a well known windows development practice when it comes to 3rd party libraries locations, we could hard-code additional paths argument (called
HINTS
) tofind_path
invocation.
I don't think there is any, unfortunately. I don't know of any myself and I couldn't find any suggestions online either.
I agree - having headers for all libraries in single default location is not ideal. My point is that additional include paths (plural), if required, meant to be configured by user via well known CMAKE_INCLUDE_PATH
variable. STB_INCLUDEDIR is just one of internal variables.
Speaking of glfw3 runtime issue - adding glfw library location to PATH
env variable is another alternative to copying the dll to each binary's folder or statically linking.
Would you consider this ready to be merged now?
Would you consider this ready to be merged now?
Yes, I think it's ready.
Nice, thanks again for the work in putting this together.
Calling
cmake --build .
will build the sample code executables for each chapter in it's own folders, compile corresponding shaders and copy all required resources to appropriate sub-folders. After that any example is ready to be run from it's build sub-folder.CMake project requires following dependencies: