include path problem when building a simple library with bazel - c++

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.

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?

Bazel can'f find my external lib header files

I'm testing bazel and now have a problem with external library.
My demo project is like this: a simple main.cpp trying to use 3rd party libary of fastcdr.
bazel-demo/
├── src
│   ├── BUILD
│   └── main.cpp
├── third_party
│   └── fastcdr
│   └── fastcdr.BUILD
└── WORKSPACE
my WORKSPACE file:
new_local_repository(
name = "fastcdr",
path = "/usr/local/fast-rtps/include",
build_file = "third_party/fastcdr/fastcdr.BUILD",
)
it defines a new package in /usr/local/fast-rtps/include, where the fastcdr library is pre-built and installed. (Please note that this is not standard /usr/local/include)
The main BUILD is like:
cc_binary(
name = "main",
srcs = [
"main.cpp",
],
deps = [
"#fastcdr"
],
)
I have added fastcdr as deps to main target.
In my fastcdr.BUILD,
cc_library(
name = "fastcdr",
includes = [
".",
],
linkopts = [
"-L/usr/local/fast-rtps/lib",
"-lfastcdr",
],
visibility = ["//visibility:public"],
)
this is the place I'm not very sure about, but it looks correct to me.
3rd party files are already there:
/usr/local/fast-rtps/
├── examples
│ └── C++
├── include
│ ├── fastcdr
│ │ ├── Cdr.h
│ │ ├── config.h
├── lib
│ ├── libfastcdr.so.1.0.7
│ └── libfastrtps.so.1.5.0
└── share
My understand is that /usr/local/fast-rtps/include is already added into the system include, so in my main.cpp, I can include the file like this:
//#include "fastrcdr/Cdr.h"
#include <fastrcdr/config.h>
int main()
{
return 0;
}
but bazel does not compile and has an error:
src/main.cpp:4:10: fatal error: fastrcdr/config.h: No such file or directory
#include <fastrcdr/config.h>
^~~~~~~~~~~~~~~~~~~
then I use --sandbox_debug to debug like this (re-formatted a little bit):
ERROR: /home/f/gitlab/bazel-demo/src/BUILD:1:10: Compiling src/main.cpp failed: (Exit 1): linux-sandbox failed: error executing command
(cd /home/f/.cache/bazel/_bazel_f/dc41fd263ad6b7cccaa1b7608cdfd5aa/sandbox/linux-sandbox/32/execroot/__main__ && \
exec env - \
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin \
PWD=/proc/self/cwd \
TMPDIR=/tmp \
/home/f/.cache/bazel/_bazel_f/install/64841bf12de13c7518c7ada0994bafe2/linux-sandbox -t 15
-w /home/f/.cache/bazel/_bazel_f/dc41fd263ad6b7cccaa1b7608cdfd5aa/sandbox/linux-sandbox/32/execroot/__main__
-w /tmp -w /dev/shm -D -- /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector
-Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++0x'
-MD -MF bazel-out/k8-fastbuild/bin/src/_objs/main/main.pic.d '-frandom-seed=bazel-out/k8-fastbuild/bin/src/_objs/main/main.pic.o' -fPIC -iquote .
-iquote bazel-out/k8-fastbuild/bin
-iquote external/bazel_tools -iquote bazel-out/k8-fastbuild/bin/external/bazel_tools
-iquote external/fastcdr -iquote bazel-out/k8-fastbuild/bin/external/fastcdr
-isystem external/fastcdr -isystem bazel-out/k8-fastbuild/bin/external/fastcdr
-fno-canonical-system-headers -Wno-builtin-macro-redefined '-D__DATE__="redacted"' '-D__TIMESTAMP__="redacted"' '-D__TIME__="redacted"'
-c src/main.cpp -o bazel-out/k8-fastbuild/bin/src/_objs/main/main.pic.o)
From this line
-w /home/f/.cache/bazel/_bazel_f/dc41fd263ad6b7cccaa1b7608cdfd5aa/sandbox/linux-sandbox/32/execroot/__main__
I know my working path.
From these two lines:
-iquote external/fastcdr -iquote bazel-out/k8-fastbuild/bin/external/fastcdr
-isystem external/fastcdr -isystem bazel-out/k8-fastbuild/bin/external/fastcdr
I know external/fastcdr & bazel-out/k8-fastbuild/bin/external/fastcdr are added into my system include.
They are relative paths, so what's the full absolute path? I assume the external and bazel-out are below my working path. I check them, neither folder has the fastcdr path.
But if I go several folder level above, there is another external folder:
dc41fd263ad6b7cccaa1b7608cdfd5aa/
├── execroot
│   └── __main__
├── external <- another `external` folder here
│   ├── bazel_tools -> /home/f/.cache/bazel/_bazel_f/install/64841bf12de13c7518c7ada0994bafe2/embedded_tools
│   ├── #bazel_tools.marker
│   ├── fastcdr <- but fastcdr is here!!!!
│   ├── #fastcdr.marker
│   ├── fastrtps
│   ├── #fastrtps.marker
│   ├── local_config_cc
├── sandbox
│   ├── inaccessibleHelperDir
│   ├── inaccessibleHelperFile
│   └── linux-sandbox <- the working path in bazel output, no fastcdr
I guess I'm very close to fix the problem, but what BUILD file should I change?
Thanks.

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.

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

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.

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?