CMake Windows find_package Imported target "..." includes non-existent path - c++

I am creating my own package that configures, builds and installs the package without problem including cmake files.
The source files are here:
https://github.com/petrasvestartas/CMAKE/tree/main/install_export
Installation procedure build SHARED libs like this:
cmake -DBUILD_SHARED_LIBS=ON -G "Visual Studio 17 2022" -A x64 .. && cmake --build . --config Release && cmake --install .
I see the files here after installation:
C:\ProgramFiles\
│ sortdemo-config-release.cmake
│ sortdemo-config.cmake
│
├───include
│ ├───print
│ │ print.hpp
│ │
│ └───sort
│ sort.hpp
│
└───lib
my_print_lib.dll
my_print_lib.lib
my_sort_lib.dll
my_sort_lib.lib
Now I want to use this package to another simple project:
https://github.com/petrasvestartas/CMAKE/blob/main/find_package/CMakeLists.txt
But I get an error:
Imported target "my_sort_lib" includes non-existent path -> include/sort files
MY SIMPLE QUESTION:
How to know where CMake searches for the files?
Since I have created the project I could modify the path, but I do not know where the problem is.

Related

g++ can't locate header files while CMake compilation is successful

I've a project structure like this:
project root
│ CMakeLists.txt
│
└───common-libs
│ │ CMakeLists.txt
│ │ libFiles.cpp
│ │ libFiles.h
│ │ ...
│
└───src
│ │ CMakeLists.txt
│ │ main.h
│ │ main.cpp
common-libs folder contains my own implementations of some functions. I can include them in main.h with #include <libFiles.h> without any problem. Cmake compiles it. Problem occured whenver I try to debug the main.cpp on Visual Studio Code. Normally I have a task.json file something like this:
{
"command": "/usr/bin/g++",
"args": [
"-std=c++17",
"-g",
"-I",
"${workspaceFolder}/common-lib/*.cpp",
"${workspaceFolder}/common-lib/*.h",
"-o",
"main",
"-lpthread"
...
]
}
There was a older version of the project where where I included the libraries with their relative path like so: #include "../common-libs/libFiles.h" and with task.json above I could debug without a problem. At that time there was no CMake in the project. While adding CMake I wanted to decouple the common-lib.
Problem
As I said, this code compiles with CMake. Although I give include directories on arguments to g++, whenever I try to run this on debug on VS Code, compiler seems to not see the files. Saying no such file or directory.
My assumption is since I'm not using any path -relative or not- and calling #include <someFile.h> like this, does compiler looks at just default directories and tries to find that file in those directories (in this case just default headers)? I either need to change the way I include header files, or I need to show the compiler where it can find the files.
What can I do to solve this?
If needed:
CMakeLists.txt on common-lib is something like this:
add_library(common-lib STATIC libFiles.cpp ...) # in reality there are more files of course
target_link_libraries(common-lib pthread curl ... )
target_include_directories(common-lib PUBLIC ${CMAKE_CURRENT_LIST_DIR})
and CMakeLists.txt on src:
add_executable(main main.h main.cpp)
target_link_libraries(main PRIVATE common-lib)

CMake warning: CMake Targets may link only to libraries. CMake is dropping the item [duplicate]

This question already has answers here:
Understanding "requests linking to directory" cmake warning
(1 answer)
CMake link to external library
(6 answers)
Closed 10 months ago.
I am making an anpr algorithm that requires tesseract to decode the image to text. When running cmake .. inside my build dir, I get a warning saying:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ cmake ..
-- Configuring done
CMake Warning at CMakeLists.txt:15 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/leptonica". Targets may link only to
libraries. CMake is dropping the item.
CMake Warning at CMakeLists.txt:16 (target_link_libraries):
Target "main" requests linking to directory
"/home/user/dev/anpr/build/libs/tesseract". Targets may link only to
libraries. CMake is dropping the item.
-- Generating done
-- Build files have been written to: /home/user/dev/anpr/build
This leads me into the thoughts that I have made something wrong. I have copied the repos for leptonica and tesseract into the libs directory for portability.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 3.2.2)
project( ANPR )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include )
include_directories(${PROJECT_SOURCE_DIR}/libs/tesseract/include)
include_directories(${PROJECT_SOURCE_DIR}/libs/leptonica/include)
link_directories(${PROJECT_SOURCE_DIR}/libs/tesseract)
link_directories(${PROJECT_SOURCE_DIR}/libs/leptonica)
add_executable( main src/main.cpp )
target_link_libraries( main ${OpenCV_LIBS} )
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/leptonica)
target_link_libraries( main ${CMAKE_CURRENT_BINARY_DIR}/libs/tesseract)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/samples/001.jpg
${CMAKE_CURRENT_BINARY_DIR}/samples/001.jpg
COPYONLY
)
and this is my project structure:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── LeptonicaTargets.cmake
│ ├── libs
│ ├── main
│ ├── Makefile
│ └── samples
├── CMakeLists.txt
...
├── include
│ └── main.hpp
├── libs
│ ├── leptonica
│ └── tesseract
...
├── samples
│ └── 001.jpg
└── src
└── main.cpp
The contents of the build dir is auto generated with cmake.
make command inside the build dir goes fine without errors even after make clean:
┌──(user㉿MacBookArch)-[~/dev/anpr/build]
└─$ make
[ 50%] Building CXX object CMakeFiles/main.dir/src/main.cpp.o
[100%] Linking CXX executable main
[100%] Built target main
How can I resolve this warning? I am open to all improvements, thank you!

Generate grpc files for a library target in CMAKE

In the following project structure(from my previous question):
root/
├─ CMakeLists.txt
├─ protocol/
│ ├─ msg.proto
│ ├─ myrpc.proto
│ ├─ CMakeLists.txt
├─ app/
│ ├─ main.cpp
│ ├─ CMakeLists.txt
I could generate the protobuf files and add them as dependency into the app target. Now I am trying to generate grpc files inside the same library.
Something is not right with the grpc generation function, which is based on this answer and blog post;as the following error message is printed:
-- Configuring done
-- Generating done
-- Build files have been written to: /media/davids91/Work/rafko/src/main/cxx/build
[ 1%] Running grpc protocol buffer compiler on /usr/local/bin/grpc_cpp_plugin
/usr/local/bin/grpc_cpp_plugin: File does not reside within any path specified using --proto_path (or -I). You must specify a --proto_path which encompasses this file. Note that the proto_path must be an exact prefix of the .proto file names -- protoc is too dumb to figure out when two paths (e.g. absolute and relative) are equivalent (it's harder than you think).
make[2]: * [protocol/CMakeFiles/protocol.dir/build.make:138: /media/usr/local/bin/grpc_cpp_plugin.grpc.pb.h] Error 1
make[1]: * [CMakeFiles/Makefile2:276: protocol/CMakeFiles/protocol.dir/all] Error 2
make: * [Makefile:103: all] Error 2
I can see that the install folder looks correct, as that is where the grpc library was installed from source.
root CMakeLists.txt:
cmake_minimum_required(VERSION 3.18.4)
project(
root
VERSION 0.1
LANGUAGES CXX
)
add_subdirectory(protocol)
add_subdirectory(app)
protocol CMakeLists.txt:
add_library(protocol)
target_include_directories(protocol
PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${Protobuf_INCLUDE_DIRS}
)
find_package(Protobuf REQUIRED)
find_package(gRPC CONFIG REQUIRED)
target_link_libraries(protocol ${Protobuf_LIBRARIES})
get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
protobuf_generate( TARGET protocol LANGUAGE CPP PROTOS msg.proto )
protobuf_generate(
TARGET
protocol
LANGUAGE
grpc
PROTOS
myrpc.proto
PLUGIN
"protoc-gen-grpc=${grpc_cpp_plugin_location}"
)
app CMakeLists.txt:
add_library(app)
target_link_libraries(app PUBLIC protocol)
target_include_directories(app PUBLIC .)
target_sources(app
PRIVATE
main.cpp
)
What might be missing from this solution to generate out the grpc files based on the plugins?
After some experimenting and closely looking at the example here I figured it out!
I updated protocol CMakeLists.txt:
changed
find_package(Protobuf REQUIRED)
to
find_package(Protobuf CONFIG REQUIRED)
I figure it tells CMake that the proto files are being procesed at configuration time, but any deeper explanation is welcome!

CMake ENV variable only accepts a single value

I am new to CMake. I'm trying to create a list of C++ source files, and build an executable using those source files. To that avoid passing the list one level at a time, I am using an environment variable. However, not all listed sources are added to the env var, only the first one is.
Here's what I have:
Directory structure:
<root>
├─ build
│ ├─ <snip>
├─ src
│ ├─ something
│ │ ├─ CMakeLists.txt
│ │ ├─ a.cpp
│ │ ├─ a.h
│ │ ├─ b.cpp
│ │ └─ b.h
│ ├─ CMakeLists.txt
│ └─ main.cpp
├─ CMakeLists.txt
root/CMakeLists.txt:
cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
project(samplecpp VERSION "0.1.0" LANGUAGES CXX)
# ---- SOURCES ----
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
set(ENV{MY_SOURCES} "")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src)
message(STATUS "MY_SOURCES = " $ENV{MY_SOURCES})
# ---- EXECUTABLE ----
add_executable(samplecpp ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp $ENV{MY_SOURCES})
root/src/CMakeLists.txt:
add_subdirectory(something)
root/src/something/CMakeLists.txt:
set(
ENV{MY_SOURCES}
$ENV{MY_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/a.cpp
${CMAKE_CURRENT_SOURCE_DIR}/b.cpp
)
Running cmake should print the message MY_SOURCES = root/src/something/a.cpproot/src/something/b.cpp, but I only get MY_SOURCES = root/src/something/a.cpp. Because of this, cmake --build fails with this error:
<root>/src/main.cpp:11: undefined reference to `B::do_b()'
What am I doing wrong?
Just in case, here's the sample on github
It is not stated in the documentation, but setting an environment variable accepts only a single value:
set(ENV{name} value)
Before 3.14 version CMake silently ignores other values.
Since 3.14 version CMake emits a warning when more than one values are passed:
Only the first value argument is used when setting an environment variable.
Source: Source/cmSetCommand.cxx
It is still possible to assign a list to the environment variable by using its semicolon-separated string representation:
# Don't work: assigns only 'a' and emits warning in CMake 4.14+
set(ENV{MY_SOURCES} a b c)
# Works: assign list of 'a', 'b', 'c' elements
set(ENV{MY_SOURCES} "a;b;c")
# The same but using intermediate CMake variable
set(MY_SOURCES_TMP a b c)
set(ENV{MY_SOURCES} "${MY_SOURCES_TMP}")

CMake add dependencies to internal library in a cousin directory

I have following project structure:
│ CMakeLists.txt
├───lib
│ │ CMakeLists.txt
│ ├───lib_a
│ │ CMakeLists.txt
│ ├───lib_b
│ │ CMakeLists.txt
│ └───lib_c
│ CMakeLists.txt
└───src
│ CMakeLists.txt
└───app
├───controller
| CMakeLists.txt
└───endorser
CMakeLists.txt
The libraries are located in lib directory. lib_b links against lib_a and lib_c links against lib_b. CMake recognizes targets between libraries with no problem. For example having these lines in lib/lib_c/CMakeLists.txt file works perfectly fine:
target_link_libraries(lib_c lib_a lib_b)
However trying to do the same in the src/app/controller fails with following error:
[cmake] CMake Error at src/app/controller/CMakeLists.txt:15 (find_package):
[cmake] By not providing "Findlib_c.cmake" in CMAKE_MODULE_PATH this project has
[cmake] asked CMake to find a package configuration file provided by "lib_c", but
[cmake] CMake did not find one.
[cmake]
[cmake] Could not find a package configuration file provided by "lib_c" with any of
[cmake] the following names:
[cmake]
[cmake] lib_cConfig.cmake
[cmake] lib_c-config.cmake
And this is how I search for lib_c:
# Check for dependencies
find_package(lib_c REQUIRED)
...
# link against it
target_link_libraries(controller lib_c)
How can I export lib_c without having to install it, in such a way that src/app can link against?
Anyway, CMakeLists.txt of non-leaf directories contain only add_subdirectory calls:
# lib/CMakeLists.txt
cmake_minimum_required(VERSION 3.1.0)
add_subdirectory(lib_a)
add_subdirectory(lib_b)
add_subdirectory(lib_c)