Visual studio project for header only library - c++

I'm creating a CMake project whose two main files are:
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(CPP_Algorithms_and_Data_Structures)
set( CMAKE_CXX_STANDARD 11 )
#add_subdirectory(./ElementaryAlgorithms)
add_subdirectory(./ElementaryDataStructures)
#add_subdirectory(./AdvancedDataStructures)
#add_subdirectory(./GraphAlgorithms)
#set(INCLUDE_FOLDERS
# ./
# ./ElementaryAlgorithms
# ./ElementaryDataStructures
# ./AdvancedDataStructures
# ./GraphAlgorithms)
set(INCLUDE_FOLDERS ./ ./ElementaryDataStructures)
set(HEADER_FILES alg-and-ds.h)
set(SRC_FILES main.cpp alg-and-ds.cpp)
add_executable(alg-and-ds ${SRC_FILES} ${HEADER_FILES})
target_include_directories(alg-and-ds PUBLIC ${INCLUDE_FOLDERS})
target_link_libraries(alg-and-ds elementary-data-structures)
#target_link_libraries(alg-and-ds
# graph-algorithms
# elementary-data-structures
# elementary-algorithms
# advanced-data-structures)
and
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(ElementaryDataStructures)
set( CMAKE_CXX_STANDARD 11 )
if(WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols")
endif()
add_library(elementary-data-structures INTERFACE)
target_include_directories(elementary-data-structures INTERFACE ./)
target_sources(elementary-data-structures INTERFACE
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc")
#set_target_properties(elementary-data-structures PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
I'm using these to generate a visual studio solution, however what I would like to do is to generate a separate project for the header only library.
Basically I had a small list library that I converted to an header only library, by using templates, before such change I was able to generate separate visual studio projects but in the same solution, in this case instead I can see something like this:
But what I'd like to see, assuming this is possible is a separate project for the ElementaryDataStructures.
I'm not an expert in CMake and all the setups, but I would be great if you could help me to figure out how to do it.
Update:
Following suggestion on the comment I got a new project in VS, however there's still a tiny bit that bothers me.
In the picture below I can see both alg-and-ds and ElementaryDataStructures_ referencing the same sources. Is there a way to avoid the alg-and-ds project to show such files?
The update CMakeLists.txt
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
project(ElementaryDataStructures)
set( CMAKE_CXX_STANDARD 11 )
if(WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols")
endif()
add_library(elementary-data-structures INTERFACE)
target_include_directories(elementary-data-structures INTERFACE ./)
target_sources(elementary-data-structures INTERFACE
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc")
add_custom_target(ElementaryDataStructures_ SOURCES ${CMAKE_CURRENT_LIST_DIR}/list.h ${CMAKE_CURRENT_LIST_DIR}/list.tcc)

As far as I know there is no normal way to do it. Only a hackish one. So you create a custom target which will force MSVC to show the project in the solution tree. Something like this:
add_custom_target(${PROJECT_NAME}_ SOURCES ${PROJECT_SOURCES})
Note the underscore in the name: it is there to differentiate it from the name in the add_library command. Of course you need to replace the variables in my example to yours actual ones.

Another solution is to declare static library with stub source file:
file(TOUCH ${CMAKE_BINARY_DIR}/stub.cpp)
add_library(elementary-data-structures STATIC
"${CMAKE_BINARY_DIR}/stub.cpp"
"${CMAKE_CURRENT_LIST_DIR}/list.h"
"${CMAKE_CURRENT_LIST_DIR}/list.tcc"
)
target_include_directories(elementary-data-structures INTERFACE ./)

Related

How to make QtCreator CMake build depend on another CMake project?

I have a CMake project that produces a static library. It compiles fine in QtCreator and produces the library in build dir. The CMakeLists.txt for the static library looks like this:
cmake_minimum_required(VERSION 3.5)
project(mystaticlib VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
file(GLOB mystaticlib_SRC "src/**.cpp")
add_library( mystaticlib STATIC
${mystaticlib_SRC}
)
target_include_directories( mystaticlib PRIVATE include/mystaticlib INTERFACE include )
Now I have a Qt application project and I'd like to make it so that it depends on the other one - meaning I can do something like in the QtProject:
cmake_minimum_required(VERSION 3.25)
project(MyQtProject VERSION 0.1 LANGUAGES CXX)
# This is how I imagine it working, not an actual code
include_project(mystaticlib, "~/my_projects/mystaticlib/CMakeLists.txt")
set(HEADERS_mystaticlib get_project_headers(mystaticlib))
# end of made up code
add_executable(MyQtProjectEXE ${PROJECT_SOURCES})
target_link_libraries(MyQtProjectEXE mystaticlib)
target_include_directories(MyQtProjectEXE HEADERS_mystaticlib)
How can I get something like that? In practice, I'd like it to work so that the dependent project directory can be set to whatever during cmake configure step.
You are most likely interested in add_subdirectory.
If the containing subdirectory has a CMakeLists.txt then by:
add_subdirectory("./path/to/the/directory")
You will include all targets defined in that CMakeLists.txt file.
All you have to do is add a dependency by using target_link_libraries. CMake will then understand that the subdirectory needs to be build beforehand.
EDIT: To use your project as an example:
cmake_minimum_required(VERSION 3.25)
project(MyQtProject VERSION 0.1 LANGUAGES CXX)
# This is how I imagine it working, not an actual code
#if the path is a subdirectory within the current folder
add_subdirectory("./local_path/to/mystaticlib")
#if not you need to specify a binary dir
add_subdirectory("/absolute/path/to/mystaticlib" "${CMAKE_CURRENT_BINARY_DIR}/mystaticlib")
set(HEADERS_mystaticlib get_project_headers(mystaticlib))
# end of made up code
add_executable(MyQtProjectEXE ${PROJECT_SOURCES})
target_link_libraries(MyQtProjectEXE mystaticlib)
#...

Do I need a Shared library in a CMAKE project with several subdirectories? How do I do it?

I need to implement a StatisticsLogger library on to a C++/C solution built with cmake and compiled with VS#2010. The project uses the ADTF API, since is built for the ADTF framework.
The solution is composed by different modules/projects, which include their own CMakeLists.txt.
My doubt/problem is regarding the library and Cmake, I need it to be accesible to every single module, but it can't be copied, them all should access the same StatisticsLogger library, that I have implemented with a Singleton.
When I run the framework, the concurrent execution accesses StatsLogger constructor once on each module, like if I had created one StatsLogger on each module, making it unable to trace together all the data I want to log and difficulting file handling.
This is how I added the library in CMakeLists.txt:
add_library(loggerModule
${DSTD_DIR}/dstdfloat.h
${DSTD_DIR}/dstdint.h
${DSTD_DIR}/dstdbool.h
${SUPT_DIR}/logg/statslogger.h
${SUPT_DIR}/logg/statslogger_c_connector.h
${SUPT_DIR}/logg/statslogger_c_connector.cpp
${SUPT_DIR}/logg/statslogger.cpp
)
#set_target_properties(loggerModule PROPERTIES VERSION ${PROJECT_VERSION})
#set_target_properties(loggerModule PROPERTIES PUBLIC_HEADER include/mylib.h)
link_libraries(loggerModule)
It would seem that adding SHARED property to the command add_library would do the job, but Im not capable of getting it working. It returns several link problems.
So, regarding my doubt, Is this the way to get the desired funcionality, to make the library SHARED? What am I doing wrong?
Main CMakeLists.txt:
# CMAKE for test filter build
cmake_minimum_required(VERSION 2.8.4 FATAL_ERROR)
# Set default install prefix
set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR})
# Set project name
project(${PROJECT_NAME})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Environment checks
find_package(ADTF 2.14.2 REQUIRED)
IF (NOT DEFINED ADTF_FOUND)
MESSAGE( FATAL_ERROR "ADTF was NOT found!!!")
ENDIF()
find_package(ADTF_DISPLAY_TOOLBOX REQUIRED)
IF (NOT DEFINED ADTF_DISPLAY_TOOLBOX_FOUND)
MESSAGE( FATAL_ERROR "ADTF_DISPLAY_TOOLBOX was NOT found!!!")
ENDIF()
set(COMPLETE_PROJECT_BINARY_OUTPUT_DIR ${CMAKE_SOURCE_DIR}/${PROJECT_BINARY_OUTPUT_DIRECTORY})
# Set path to sw module dependencies
set(COMMON_DIR ${CMAKE_SOURCE_DIR}/common)
set(DSTD_DIR ${CMAKE_SOURCE_DIR}/common/dstd)
set(INTF_DIR ${CMAKE_SOURCE_DIR}/common/intf)
set(SUPT_DIR ${CMAKE_SOURCE_DIR}/common/supt)
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
#option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
include_directories(${DSTD_DIR})
include_directories(${SUPT_DIR}/logg)
add_library(loggerModule SHARED
${DSTD_DIR}/dstdfloat.h
${DSTD_DIR}/dstdint.h
${DSTD_DIR}/dstdbool.h
${SUPT_DIR}/logg/statslogger.h
${SUPT_DIR}/logg/statslogger_c_connector.h
${SUPT_DIR}/logg/statslogger_c_connector.cpp
${SUPT_DIR}/logg/statslogger.cpp
)
#set_target_properties(loggerModule PROPERTIES VERSION ${PROJECT_VERSION})
#set_target_properties(loggerModule PROPERTIES PUBLIC_HEADER include/mylib.h)
link_libraries(loggerModule)
# Set commands for BB nodes generation
# ...and dependencies for generation
# Go into sub-directory with filter sources
add_subdirectory(${CMAKE_SOURCE_DIR}/tool/adtf/af_acca)
#[33 other add_subdirectories commands]
Example subdirectory CMakeLists.txt:
# External required components have to be provided with path variables
# Internal required components have to be connected to the source file list
if(NOT DEFINED DSTD_DIR)
message( FATAL_ERROR "AF_CDAS requires DSTD_DIR" )
endif()
if(NOT DEFINED INTF_DIR)
message( FATAL_ERROR "AF_CDAS requires INTF_DIR" )
endif()
if(NOT DEFINED SUPT_DIR)
message( FATAL_ERROR "AF_CDAS requires SUPT_DIR" )
endif()
set(CDAS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../)
include_directories(${COMMON_DIR})
[some more includes]
#
# CDAS FILES
#
set(CDAS_FILES
${CDAS_DIR}/src/cdas/cdas.c
${CDAS_DIR}/src/cdas/cdas.h)
source_group("cdas\\files" FILES ${CDAS_FILES})
#
# CDAS ADTF WRAPPER
#
set(CDAS_ADTF_WRAPPER
${CDAS_DIR}/tool/adtf/af_cdas/af_cdas_conf.h
${CDAS_DIR}/tool/adtf/af_cdas/af_cdas.h
${CDAS_DIR}/tool/adtf/af_cdas/af_cdas.cpp)
source_group("cdas\\adtf" FILES ${CDAS_ADTF_WRAPPER})
adtf_add_filter(CDAS
# List source and header files of your filter and its required components
# ${MAIN_FILES}
${CDAS_FILES}
${CDAS_ADTF_WRAPPER}
)
# stdafx.h workaround
if (MSVC)
set_target_properties(CDAS PROPERTIES COMPILE_FLAGS "/Y-")
endif(MSVC)
# MANDATORY PATH SETTING !!!
install (TARGETS CDAS DESTINATION ${COMPLETE_PROJECT_BINARY_OUTPUT_DIR}/debug CONFIGURATIONS Debug)
install (TARGETS CDAS DESTINATION ${COMPLETE_PROJECT_BINARY_OUTPUT_DIR}/release CONFIGURATIONS Release)
adtf_set_folder(CDAS filter)
When using this files, I get the following error:
LINK : fatal error LNK1181: cannot open input file '......\Release\loggerModule.lib' [C:\Users\inno\Desktop\rad
ar_processing\test\adtf\build\win64_vc100\tool\adtf\af_aoca\AOCA.vcxproj]
There isn't any loggerModule.lib in the Release folder, but a loggerModule.dll. In the Debug folder there is a .lib, but copying it to Release won't solve the problem.
I never got too familiar with Cmake, and I am trying to learn it, so I don't know what is going on here, if I am doing something wrong, or my approach wasn't good from the beggining.

CMake BUILD undefined reference (findpng)

I'm still very new to CMake so feedback is definitely welcome. So, I'm trying to build a simple application that should eventually create a pdf using the library libharu.
I think i figured it out how to link the library. But I still receive build errors for the findpng module (I suppose libharu depends on it)
CMakeLists.txt:
cmake_minimum_required(VERSION 3.2.0 FATAL_ERROR) # current latest stable version (if lower give FATAL_ERROR)
project(pdf_generator VERSION 0.1.0) # name of the project, version.
file(GLOB TARGET_SRC "./src/*.cpp") # Creates variable, using globbing.
include_directories(${PROJECT_SOURCE_DIR}/include) # list of directories to be used as header search paths.
add_executable(main ${TARGET_SRC}) # Create an executable of set of source files [exe name files to bundle].
find_library(libhpdf_location NAMES libhpdf.a) # find the location of libhpdf.a and save the value in the variable libhpdf_location.
message(STATUS ${libhpdf_location}) # print status of variable.
add_library(libhpdf STATIC IMPORTED) # Add library via a static import.
set_target_properties(
libhpdf PROPERTIES
IMPORTED_LOCATION ${libhpdf_location}
)
target_link_libraries(main libhpdf)
I've never worked with that particular library before, but skimming their CMakeLists.txt on GitHub it seems like libharu has optional dependencies on libpdf and zlib. Without knowing how you built your version of libharu I'm going to assume that both are needed.
Luckily, CMake comes with find-modules for both libpng and zlib, so adding the following should work:
find_package(PNG REQUIRED)
find_package(ZLIB REQUIRED)
set_target_properties(libhpdf
PROPERTIES
INTERFACE_LINK_LIBRARIES "ZLIB::ZLIB;PNG::PNG"
)
Looks like all you need to do is tell cmake to link libpng.

Can values be set for CMake SOURCE(S) other than using set?

Suppose I have a simple C++ hello-world project with the following CMake script:
cmake_minimum_required(VERSION 3.15)
project(hello)
set(SOURCE main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE})
Now I noticed that PROJECT_NAME is built-in and its value is set from project(*value*) but also SOURCE (and SOURCES) seems to be provided by CMake too.
Are there other ways where SOURCE can be assigned with project source files? Just like the same behavior with PROJECT_NAME. Or is set(SOURCE ...) the intended method.
I'm new to CMake. The SOURCE and SOURCES variables were colored out on my text editor. I'm confused.
Using a SOURCE variable is a common patter in CMake files, but it is not required.
The code above can be written without any variables, it would look something like this:
add_executable(hello main.cpp)
When there are a lot of source files, passing them all to add_executable can be inconvenient. Another alternative is target_sources:
add_executable(hello)
target_sources(hello PRIVATE main.cpp)

Using SDL2 with CMake in CLion

After hours of scouring the web and SO for a solution I'm at a standstill. Nothing has worked so far for me...
I'm on Windows, using CLion IDE which uses CMake. My goal is to correctly link SDL2 to my project and use it through #include "SDL.h" which is the correct way.
The format of my CMakeLists.txt file
Specifics regarding the directory where I should have put the MingW development library of SDL2
Any requirements regarding windows ENV variables that I might have to set.
My CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.6)
project(sdl2Project)
set(CMAKE_CXX_STANDARD 11)
#This is where sdl2-config.cmake is located
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:/Users/MyUserName/CLibraries/SDL2-2.0.5/x86_64-w64-mingw32/lib/cmake/SDL2")
set(SOURCE_FILES main.cpp)
add_executable(sdl2Project ${SOURCE_FILES})
find_package(sdl2 REQUIRED)
target_include_directories(sdl2Project PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(sdl2Project ${SDL2_LIBRARIES})
There is no FindSDL2.cmake file used.
The SDL2 library I downloaded from libsdl.org is located in:
C:/Users/MyUserName/CLibraries/SDL2-2.0.5/x86_64-w64-mingw32
I have no experience with CMake so I'm unable to truly understand where the problem stems from. What are the steps I need to take in order for it to find the library and link it correctly??
EDIT:
My Project structure is the following:
sdl2Project
cmake-build-debug
CMakeLists.txt
main.cpp
Looking in your FindSDL2.cmake, you need to provide an hint to CMake about where the library is installed. You could do this by setting an environment variable SDLDIR, but you shouldn't. General advice: you shouldn't use a CMake package that wasn't provided with the sources you're using.
Looking in sources of SDL2, root directory contains a file sdl2-config.cmake.in that should have been configured and installed in your install directory as sdl2-config.cmake: that's the package file you should use.
Am I right guessing the file C:/Users/MyUserName/CLibraries/SDL2-2.0.5/sdl2-config.cmake exists?
If yes, to allow CMake to find it, add your install directory to CMAKE_PREFIX_PATH, before calling find_package:
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
"C:/Users/MyUserName/CLibraries/SDL2-2.0.5"
)
find_package(sdl2 REQUIRED)
Note the use of "/" in the path instead of "\" which could be interpreted as escaping character. Quotes around the path are only necessary if the path contains whitespaces.
EDIT:
Moreover, you misused target_link_libraries with a wrong target: SDL2 which you don't build in your project, instead of sdl2Project.
You also used a wrong variable: SDL2_LIBRARY instead of SDL2_LIBRARIES; you can see the good variable name by looking in sdl2-config.cmake.
You may consider target_include_directories instead of include_directories, but again the variable name you used is wrong: SDL2_INCLUDE_DIR instead of SDL2_INCLUDE_DIRS.
Try:
target_include_directories(sdl2Project PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(sdl2Project ${SDL2_LIBRARIES})