CMake - Create executable for all *.cpp file in folder - c++

I have this folder tree:
benchmark/
├─ pair/
│ ├─ benchmark_create.cpp
│ ├─ benchmark_insert.cpp
│ ├─ benchmark_remove.cpp
├─ set/
├─ CMakeLists.txt
And this is my current CMakeLists.txt file content:
add_executable(dbg_pair_creation pair/benchmark_creation)
target_link_libraries(pair_creation benchmark::benchmark)
add_executable(dbg_pair_insert pair/benchmark_insert)
target_link_libraries(pair_insert benchmark::benchmark)
add_executable(dbg_pair_remove pair/benchmark_remove)
target_link_libraries(pair_remove benchmark::benchmark)
There is a compacxt way to do the same and to put this executable in a folder with name pair that is the folder name of the source?

You could use a foreach loop.
set(benchmarks creation insert remove)
foreach (benchmark IN LISTS benchmarks)
add_executable(dbg_pair_${benchmark} pair/benchmark_${benchmark}.cpp)
target_link_libraries(dbg_pair_${benchmark} PRIVATE benchmark::benchmark)
set_property(
TARGET dbg_pair_${benchmark}
PROPERTY RUNTIME_OUTPUT_DIRECTORY
"${CMAKE_CURRENT_BINARY_DIR}/dbg_pair_${benchmark}"
)
endforeach ()
Then you would just need to add to the benchmarks list when you add a new benchmark.

Related

Dependency header not found for sub directory in cmake

I have the following project structure
sandbox/
├── CMakeLists.txt
├── external
│ └── test_pkg
│ ├── CMakeLists.txt
│ ├── cmake
│ │ └── FindOnnxruntime.cmake
│ ├── include
│ │ └── pkg
│ │ └── test.hpp
│ └── src
│ ├── main.cpp
│ └── test.cpp
├── include
│ └── sandbox
│ └── sandbox.hpp
└── src
└── node.cpp
with sandbox/external/test_pkg/CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(test_pkg VERSION 0.1.0)
set(lib_target_name ${PROJECT_NAME}) # name of the library created by this project
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FindOnnxruntime.cmake)
message("onnx includes: ${onnxruntime_INCLUDE_DIRS}")
message("onnx libraries: ${onnxruntime_LIBRARIES}")
# setup based on GPU
set(CMAKE_CUDA_ARCHITECTURES 86)
include_directories(
include
${onnxruntime_INCLUDE_DIRS}
)
add_library(${lib_target_name} SHARED
src/test.cpp
)
target_link_libraries(${lib_target_name}
${onnxruntime_LIBRARIES}
)
include(GNUInstallDirs)
target_include_directories(${lib_target_name}
PRIVATE
# where the library itself will look for its internal headers
${CMAKE_CURRENT_SOURCE_DIR}/include
PUBLIC
# where top-level project will look for the library's public headers
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
# where external projects will look for the library's public headers
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
add_executable(test_main src/main.cpp)
target_link_libraries(test_main
${lib_target_name}
)
install(TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}Targets"
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/pkg" # source directory
DESTINATION "include" # target directory
PATTERN "*.hpp" # select header files
)
sandbox/external/test_pkg/cmake/FindOnnxruntime.cmake
unset(onnxruntime_FOUND)
unset(onnxruntime_INCLUDE_DIRS)
unset(onnxruntime_LIBRARIES)
set(onnxruntime_INSTALL_PATH "/opt/onnxruntime")
find_path(onnxruntime_INCLUDE_DIRS NAMES onnxruntime_cxx_api.h
PATHS "${onnxruntime_INSTALL_PATH}/include")
find_library(onnxruntime_LIBRARIES
NAMES libonnxruntime.so
PATHS "${onnxruntime_INSTALL_PATH}/lib")
set(onnxruntime_INCLUDE_DIRS ${onnxruntime_INCLUDE_DIRS})
set(onnxruntime_LIBRARIES ${onnxruntime_LIBRARIES})
if(onnxruntime_INCLUDE_DIRS AND onnxruntime_LIBRARIES)
set(onnxruntime_FOUND 1)
endif(onnxruntime_INCLUDE_DIRS AND onnxruntime_LIBRARIES)
and top level sandbox/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(sandbox)
add_subdirectory("external/test_pkg")
include_directories(
include
external/test_pkg/include
)
add_executable(sandbox_node src/node.cpp)
target_link_libraries(sandbox_node
test_pkg
)
test_pkg project compiles fine standalone with cmake
When I use it as a subdirectory as above I get external/test_pkg/include/pkg/test.hpp:1:10: fatal error: onnxruntime_cxx_api.h: No such file or directory 1 | #include <onnxruntime_cxx_api.h>
What am I doing wrong here?

cmake files for projects structure where child c++ classes inherits parents classes

I have c++ project with structure like this:
src
| CMakeLists.txt (?)
|
└─── project
| base_0.hpp
│ base_0.cpp (defines Base_0 class)
│
└───folder_1
│ │ base_1.cpp
│ │ base_1.hpp (defines Base_1 class, which inharits Base_0 class)
│ │
│ └───subfolder_1
│ │ base_2.cpp
│ │ base_2.hpp (defines Base_2 class, which inharits Base_1 class)
│ │ ...
│
└───folder_2
│ base_12.cpp
│ base_12.hpp
I have no idea how to build a project with such structure, anywhere I read about it there was written about the simplest structure
I tried with CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(lib_project VERSION 0.0.1)
set(LIBRARY_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/project/base_0.hpp
${CMAKE_CURRENT_SOURCE_DIR}/project/folder_1/base_1.hpp
${CMAKE_CURRENT_SOURCE_DIR}/project/folder_1/subfolder_1/base_2.hpp
)
set(LIBRARY_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/project/base_0.cpp
${CMAKE_CURRENT_SOURCE_DIR}/project/folder_1/base_1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/project/folder_1/subfolder_1/base_2.cpp
)
set(ALL_FILES ${LIBRARY_HEADERS} ${LIBRARY_SOURCES})
add_library(library STATIC ${ALL_FILES})
set_target_properties(
library PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
)
target_include_directories(
library
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
install(
TARGETS library EXPORT libraryTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
)
install(
FILES ${ALL_HEADER_FILES} DESTINATION include
)
install(
EXPORT libraryTargets
FILE libraryConfig.cmake
NAMESPACE Library::
DESTINATION lib/cmake/library
)
I read about subdirectories in CMake, but I think it's not applied for this structure.

Include mly files nested in subdirectories when compiling with dune

Say I have the following directory:
.
├── dune-project
├── myproj.opam
└── src
├── dune
├── module1.ml
├── parser1
│   └── file1.ml
└── parser2
└── file2.ml
Since I want everything to be in the same library, I have the following:
src/dune:
(include_subdirs unqualified)
(library
(name myproj)
(modules module1 file1 file2)
)
And it compiles perfectly well.
Now, the thing is, my file1 and file2 are actually mly files so I have this:
.
├── dune-project
├── myproj.opam
└── src
├── dune
├── module1.ml
├── parser1
│   └── parser1.mly
└── parser2
└── parser2.mly
If I try to compile (by changing file(1|2) by parser(1|2) in the dune file), I have the following error:
❯ dune build
File "src/dune", line 5, characters 26-33:
5 | (modules module1 parser1 parser2 )
^^^^^^^
Error: Module Parser2 doesn't exist.
I edit my dune file:
(include_subdirs unqualified)
(menhir
(modules parser1 parser2)
)
(library
(name myproj)
(modules module1 parser1 parser2 )
)
Two errors now:
❯ dune build
File "src/dune", line 3, characters 0-36:
3 | (menhir
4 | (modules parser1 parser2)
5 | )
Error: No rule found for src/parser1.mly
File "src/dune", line 3, characters 0-36:
3 | (menhir
4 | (modules parser1 parser2)
5 | )
Error: No rule found for src/parser2.mly
Ok, I then add two dune files in parser(1|2) directories:
(menhir
(modules parser(1|2))
)
[EDIT] Looks like I missed something but this was actually working pretty well
And I now have the same error as before:
❯ dune build
File "src/dune", line 5, characters 26-33:
5 | (modules module1 parser1 parser2 )
^^^^^^^
Error: Module Parser2 doesn't exist.
Am I missing something to please dune? (I have the same problem if I have .mll files)
The menhir stanza doesn't work with subdirs. It is a bug that is not yet fixed1. There are a couple of workarounds, like adding the dune file to the folder where you have the parser (didn't check it myself). But I would suggest splitting the parsers into separate libraries or moving them to the src folder. The former is preferred, especially since then you won't need to write the modules stanza.
1)As of January 2022

include path problem when building a simple library with bazel

The demo structure like this:
.
├── demo
│ ├── include
│ │ └── func.h
│ │
│ └── src
│ ├── BUILD
│ │
│ └── func.cc
└── WORKSPACE
func.h:
#pragma once
int square(int);
func.cc: include from the root
#include "demo/include/func.h"
int square(int i) { return i * i; }
BUILD:
cc_library(
name = "simple_demo",
srcs = ["func.cc"],
visibility = ["//visibility:public"],
)
Bazel build command in the dir of WORKSPACE:
bazel build //demo/src:simple_demo
The error occurs.
demo/src/func.cc:1:10: fatal error: 'demo/include/func.h' file not found
And I saw this in https://docs.bazel.build/versions/1.1.0/be/c-cpp.html#hdrs
All header files that are used in the build must be declared in the hdrs or srcs of cc_* rules. This is enforced.
However, if I add hdrs = "../include/func.h" to the BUILD, another error will occur
segment '..' not permitted
By default in Bazel labels are not allowed to cross the package boundaries. In your case func.h lives outside the package defined by the BUILD file, that is limited to demo/src (and sub-folders).
Assuming you're creating a library where func.h is the public header visible from outside, I would change the folder structure to:
.
├── demo
│ ├── include
│ │ └── func.h
│ ├── src
│ │ └── func.cc
│ └── BUILD
└── WORKSPACE
and the BUILD file to also include func.h:
cc_library(
name = "simple_demo",
hdrs = ["include/func.h"],
srcs = ["src/func.cc"],
visibility = ["//visibility:public"],
)
Notice that even with the suggested folder structure, if you don't include the hdrs = ... line (or don't include func.h in srcs = ..., if the header is not meant to be public), you will get an error for the reason you mentioned.
I am not sure if this might work, but can you try giving
'../include/func.h'
instead of 'demo/include/func.h' because I believe its not able to find a demo folder inside your src folder since it starts searching from there.

cmake can't find header file?

I am not sure I understand why I am having this problem..
but cmake seem to have some problems with finding the header file located in a different project.
tree view of my system:
tree
.
├─ build
├─ CMakeLists.txt
├─ src
├── CMakeLists.txt
├── include
│ ├── CMakeLists.txt
│ ├── database
│ │ ├── CMakeLists.txt
│ │ ├── database.cpp
│ │ └── database.h
│ ├── match
│ │ ├── CMakeLists.txt
│ │ ├── match.cpp
│ │ └── match.h
│ ├── record
│ │ ├── CMakeLists.txt
│ │ ├── record.cpp
│ │ └── record.h
│ └── spectogram
│ ├── CMakeLists.txt
│ ├── spectogram.cpp
│ └── spectogram.h
└── main.cpp
I’ve included the directory to the project which header files I am interested in, and also added the path in my
target_inlcude_directories. The problems is my database.h cannot see record.h.
database/CmakeLists.txt:
project(database)
MESSAGE(“In database CMAKELIST”)
#
# Build static library
add_library(database database.cpp database.h)
include_directories(${record_SOURCE_DIR} ${spectogram_SOURCE_DIR})
target_compile_features(database PUBLIC cxx_defaulted_functions)
target_include_directories(database PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${record_SOURCE_DIR} ${spectogram_SOURCE_DIR})
record/CMakeList.txt:
project(record)
MESSAGE( “In record CMAKELIST” )
# Include externalproject {portaudio} if lib/portaudio don't exist.
INCLUDE(ExternalProject)
ExternalProject_Add(project_portaudio
GIT_REPOSITORY https://git.assembla.com/portaudio.git
PREFIX lib/portaudio
UPDATE_COMMAND ""
CONFIGURE_COMMAND <SOURCE_DIR>/configure --enable-cxx
BUILD_IN_SOURCE 0
BUILD_COMMAND make
INSTALL_COMMAND sudo make install
)
ExternalProject_Get_Property(project_portaudio BINARY_DIR)
ExternalProject_Get_Property(project_portaudio SOURCE_DIR)
SET(portaudio_lib_dir "${BINARY_DIR}/lib/.libs")
SET(portaudio_inc_dir "${SOURCE_DIR}/include")
add_library(record STATIC record.cpp record.h AudioFile.cpp AudioFile.h)
add_library(portaudio STATIC IMPORTED)
set_target_properties(portaudio PROPERTIES
IMPORTED_LOCATION "${portaudio_lib_dir}/libportaudio.so")
set_property(TARGET portaudio APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES ${SOURCE_DIR}/include)
add_dependencies(portaudio project_portaudio) # Not sure if this is allowed for imported targets though
find_package(Threads REQUIRED)
find_package(ALSA REQUIRED)
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(EXTRA_LIBS rt asound jack)
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
#
# this makes sure we have compiler flags that allow class::class() = default (>= C++11)
target_link_libraries(record PUBLIC ${EXTRA_LIBS} ${ALSA_LIBRARIES} portaudio Threads::Threads )
target_compile_features(record PUBLIC cxx_defaulted_functions)
target_include_directories(record PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${project_portaudio})
The weird part is that it sometimes is able to compile, and other times it get stuck with this not able to find the header?
what could the problem be?