I'm trying to apply modern CMake practices in my project.
And I've came up with an issue with the {fmt} library dependency.
The structure of a project is the following (in a brief):
dev/
|
+--- fmt/ *unpacked archive of 4.1.0 version*
|
+--- mylib/
| |
| +--- mylib.hpp
| |
| +--- CMakeLists.txt
| ***************************
| * ...
| * add_library(mylib INTERFACE)
| * TARGET_LINK_LIBRARIES(mylib PUBLIC fmt-header-only)
| * set(MYLIB_HEADERS_ALL mylib.hpp )
| * ...
| ***************************
|
+--- sample/
| |
| +--- main.cpp
| |
| +--- CMakeLists.txt
| ***************************
| * set(SAMPLE sample.hello_world)
| * add_executable(${SAMPLE} main.cpp)
| * TARGET_LINK_LIBRARIES(${SAMPLE} PRIVATE mylib)
| * install(TARGETS ${SAMPLE} DESTINATION bin)
| ***************************
|
+--- CMakeLists.txt
***************************
* include_directories(${CMAKE_CURRENT_SOURCE_DIR})
* add_subdirectory(fmt EXCLUDE_FROM_ALL)
* add_subdirectory(sample/hello_world)
***************************
When I try to build it I receive an error:
PATH/mylib/mylib.hpp:6:10: fatal error: fmt/format.hpp: No such file or directory
#include <fmt/format.hpp>
^~~~~~~~~~~~~~~~
compilation terminated.
Full reproduction can be found here:
https://bitbucket.org/ngrodzitski/cmake-issue-fmt-20180410
Any suggestions on the issue?
With the help from Mathieu Ropert in slack, I've resolved the issue in following steps:
TARGET_LINK_LIBRARIES(mylib INTERFACE fmt::fmt-header-only) in mylib/CMakeLists.txt (PUBLIC before).
add the following to root CMakeLists.txt: add_subdirectory(mylib) (that what makes a change).
I pushed final version to repo: https://bitbucket.org/ngrodzitski/cmake-issue-fmt-20180410.
Related
I have the following folder structure:
Project
|-Sources
| |-Package1
| |-Component11
| |-include
| |-header.hpp
| |-src
| |-source.cpp
| |-CMakeLists.txt
| |-Component12
| |-include
| |-header.hpp
| |-src
| |-source.cpp
| |-CMakeLists.txt
| |-CMakeLists.txt
| |-Package2
| |-Component21
| |-...
| |-Component22
| |-...
| |-CMakeLists.txt
| |-CMakeLists.txt
|-CMakeLists.txt
Lets say that in this design the component21 have a dependency on component11.
I would like to include the header files of component11 in this component as:
#include<Project/Package1/Component11/header.hpp> without repeating this path in include folder of component11 by creating sub directories there. Is there a way in cmake that i can achieve this?
UPDATE:
It's working but I don't know what happened so I will leave the question open.
I am trying to add zlib. For this purpose I have added the following configuration file that is included in my main CMakeLists.txt.
include(ExternalProject)
set(DEPS_BUILD ${CMAKE_BINARY_DIR}/deps/build)
set(DEPS_LOG ${CMAKE_BINARY_DIR}/deps/log)
set(DEPS_STAMP ${CMAKE_BINARY_DIR}/deps/stamp)
set(DEPS_TMP ${CMAKE_BINARY_DIR}/deps/tmp)
set(DEPS_SRC ${CMAKE_BINARY_DIR}/deps/src)
ExternalProject_Add(zlib
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/deps/zlib
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
DOWNLOAD_DIR ${DEPS_SRC}/zlib
TMP_DIR ${DEPS_TMP}/zlib
STAMP_DIR ${DEPS_STAMP}/zlib
LOG_DIR ${DEPS_LOG}/zlib
BINARY_DIR ${DEPS_BUILD}/zlib
SOURCE_DIR ${DEPS}/zlib
INSTALL_COMMAND cmake -E echo "Skipping install step for dependency zlib"
INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
)
I am using CMake 2.21 (latest as of 9th of September 2021) and Visual Studio 2017. I have of course added zlib as a dependency like this:
add_dependencies(${MY_LIB} zlib)
where MY_LIB is the library. The ${DEPS} variable points at a subdirectory (inside the root directory of my project) where all git submodules are currently being initialized.
${CMAKE_SOURCE_DIR}
|
+ --- CMakeLists.txt
|
+ --- ${DEPS}
| |
| + --- dependencies.cmake
| |
| + --- zlib git submodule
| |
| + --- libpng git submodule
| |
| + --- libjpeg-turbo git submodule
...
Also the reason why I define all the variables below is mostly for structural purposes. The first time I added the ExternalProject stuff and ran my configuration it created a lot of directories all over the place inside my build directory. By defining specific locations I can ensure the structure I want and come in terms with:
${CMAKE_BINARY_DIR}
|
+ --- CMakeFiles
|
+ --- CMakeCache.txt
|
...
|
+ --- deps
| |
| + --- build
| | |
| | + --- jpeg
| | |
| | + --- png
| | |
| | + --- zlib
| |
| + --- src
| | |
| | + --- jpeg
| | |
| | + --- png
| | |
| | + --- zlib
| |
| |
| + --- stamp
| | |
| | ...
| |
| + --- tmp
| |
| ...
|
...
I am working on and which uses zlib's functionality internally. After generating the VS solution (with the ZERO_BUILD, ALL_BUILD etc. projects added to it) for VS 2017 64bit debug build I tried to build the zlib project just to see if it work properly but I am getting the following error:
Performing build step for 'zlib'
CUSTOMBUILD : error : could not load cache
I have successfully added turbojpeg to my project (with the same code) and it works without any issues. Given my previous experience with zlib when building 3rd party software (libs, executables) I am inclined to think that there is some configuration step missing. What that step might be is beyond me. I am also new to the ExternalProject module of CMake.
I'm trying to include libheif into my project using cmake. Libheif is more complicated than what I've worked with before because it requires you externally build and include libde265.
Attempt #1:
I have used vcpkg to export pre-built binary packages, this creates a directory called libheif which includes everything here:
+---bin
| heif.dll
| libde265.dll
| libx265.dll
| libx265.pdb
|
+---debug
| +---bin
| | heif.dll
| | libde265.dll
| | libx265.dll
| | libx265.pdb
| |
| \---lib
| | heif.lib
| | libde265.lib
| | libx265.lib
| | x265-static.lib
| |
| \---pkgconfig
| libheif.pc
| x265.pc
|
+---include
| | x265.h
| | x265_config.h
| |
| +---libde265
| | de265.h
| |
| \---libheif
| heif.h
|
+---lib
| | heif.lib
| | libde265.lib
| | libx265.lib
| | x265-static.lib
| |
| \---pkgconfig
| libheif.pc
| x265.pc
|
+---share
| +---libde265
| | copyright
| | libde265Config-debug.cmake
| | libde265Config-release.cmake
| | libde265Config.cmake
| | libde265ConfigVersion.cmake
| | vcpkg_abi_info.txt
| |
| +---libheif
| | | copyright
| | | libheif-config-debug.cmake
| | | libheif-config-release.cmake
| | | libheif-config-version.cmake
| | | libheif-config.cmake
| | | vcpkg_abi_info.txt
| | |
| | \---.vs
| | ProjectSettings.json
| | slnx.sqlite
| |
| \---x265
| copyright
| vcpkg_abi_info.txt
|
\---tools
+---libde265
| dec265.exe
| enc265.exe
| libde265.dll
|
\---x265
x265.exe
(There were more headers, I removed them because one illustrates the point) I put folder libheif in my external folder in my project. Then in CMakeLists.txt I have tried using
target_link_libraries(my_project ${CMAKE_SOURCE_DIR}/external/libheif/lib/heif)
that then fails looking for heif.obj file that is not there. It does find the dlls though.
After that failed, I tried again, this time using the .cmake files in the share directory:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/external/libheif/share/libheif)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/external/libheif/share/libde265)
include(libheif-config)
include(libde265Config)
This I get unresolved external symbol when trying to use anything in libheif.
Attempt #2:
I tried including libeheif by adding it as a submodule git submodule add https://github.com/strukturag/libheif.git external/libheif
and then in CMakeLists.txt I added:
include_directories(external/libheif/include)
include_directories(external/libheif/include/libheif)
include_directories(external/libheif/include/libde265)
add_subdirectory(external/libheif)
target_link_libraries(my_project libheif)
This results in unresolved external symbols whenever I try to use anything in the libheif library.
Other information
The only successful thing I have been able to do is include the headers directory so intellisence recognizes when I #include <heif.h>
I have looked all over on how to include dll and libraries, but all the results either need me to use the cmake GUI, which I am not sure I can because I'm working on this project with other people and I want to make sure it works on their computer without having to use the cmake GUI.
Same with just using vcpkg to include it, I dont want my teammates to have to use it as well, I need to just use CMakeLists.txt
This tutorial would be helpful but the generate stuff is above my head and I couldnt find what it meant by generate. It might be a rabbit hole I loose a day over.
I am working on Windows 10, I will eventually need to make it so it can build on OSX but I'm just trying to get it to work on windows for now.
I am trying to understand why each of these approaches failed. I would rather go down the path of attempt #2 because I feel like that is better for down the road when I need to make it compile for mac as well. Thank you.
Then in CMakeLists.txt I have tried usingļ¼
target_link_libraries(my_project
${CMAKE_SOURCE_DIR}/external/libheif/lib/heif)
I think you should use:
target_link_directories( ${PROJECT_NAME}
PRIVATE ./external/libheif/lib/heif
)
target_link_libraries( ${PROJECT_NAME} PRIVATE
heif
xxx
)
target_link_directories : Add link directories to a target.
Description
I'm currently creating a program that would turn a model from simulink and matlab into an FMU.
As I want to automate the process as much as possible I want to also automate the build process for both an EXE, to extract information in the C-API supplied, and later a DLL for the FMU. My plan was to do this with CMake, which is why I'm here. As I know the layout of the code generation (See further down), I could go ahead and make multiple CMakeLists and just have a part of my python script paste them into their repsective folders. BUT, I wanted to make sure this was the only way of doing it (Multiple CMakeLists) before going ahead.
Question
Is there anyway to only have one CMakeLists with many multiple categories? Do I just include all subfolders that include files with target_include_directories() or have I understood that completely wrong? Is there a way to make target_include_directories() to also include subfolders?
My current directory looks like this:
\---CMakeListExperiment
| main.c
| CMakeLists.txt <--- Is it possible to make this the only CMakeLists?
|
+---R2017b
| |
| |
| +---extern
| | \---include
| | tmwtypes.h
| |
| +---rtw
| | \---c
| | \---src
| | | rt_logging.h
| | | rtw_capi.h
| | | rtw_modelmap_logging.h
| | | rt_logging.c
| | | rt_mxclassid.h
| | | rt_logging_mmi.c
| | | rtw_modelmap.h
| | | rt_logging_mmi.h
| | | rtw_modelmap_utils.c
| | |
| | +---common
| | | rt_main.c
| | |
| | \---ext_mode
| | \---common
| | ext_work.h
| |
| \---simulink
| \---include
| rtw_matlogging.h
| sysran_types.h
| rtw_extmode.h
| sl_sample_time_defs.h
| simstruc_types.h
| sl_types_def.h
| rtw_solver.h
| rtw_continuous.h
|
+---multi_grt_rtw
| rtGetInf.c
| rtwtypes.h
| rt_nonfinite.h
| multiword_types.h
| multi_capi.h
| rtmodel.h
| buildInfo.mat
| defines.txt
| rtGetNaN.h
| builtin_typeid_types.h
| rt_nonfinite.c
| multi_capi.c
| rtGetNaN.c
| multi.h
| multi_capi_host.h
| rtGetInf.h
| multi_private.h
| multi_types.h
| multi_data.c
| multi.c
I'm usually very bad at explaining things, so if there's any confusion let me know. I'm also new to posting at SO, which is why I would love feedback. Cheers
EDIT 1:
I have tried the following CMakeLists. I can get this working if I move all sourcefiles inside "/multi_grt_rtw/, but will fail if these files are in their folders that comes produced by matlab. Fail as in "can't find files".
cmake_minimum_required(VERSION 3.0)
project(hello-vsc C)
file(GLOB_RECURSE SOURCES_NORMAL RELATIVE ${CMAKE_SOURCE_DIR} "multi_grt_rtw/*.c")
file(GLOB_RECURSE SOURCES_MATLAB RELATIVE ${CMAKE_SOURCE_DIR} "R2017b/*.c")
set(SOURCE main.c)
include_directories(${CMAKE_SOURCE_DIR}/multi_grt_rtw)
include_directories(${CMAKE_SOURCE_DIR}/R2017b)
add_executable(main ${SOURCE} ${SOURCES_NORMAL} ${SOURCES_MATLAB})
My guess is that include_directories is not recursive (Not searching subdirectories for sourcefiles), so my question is if there's any way to do that? Make include_directories recursive?
The other two, in theory?, working options are
A) As everything is always produced the same, write all CMakeLists needed and copy them, with a script, to correct folder during execution.
B) Add multiple include_directories() to main directory CMakeLists
Now when I have had some time away from work, I guess my question is a bit weird. But it would still be intresting finding out if include_directories() could be used in the way I want it to be, as I can't find much information about it.
All of my projects have the following structure tree:
project
|----utils
| |----util_1
| | |----inc_directory(hpp files inside)
| | |----src_directory(cpp files inside)
| ..........
| ..........
| |----util_n
| | |----inc_directory(hpp files inside)
| | |----src_directory(cpp files inside)
|
|----main.cpp
|----CMakeLists.txt
I want to write a generic CMakeLists.txt file that will allow me to compile any project which has the same structure.