I am trying to integrate grpc with a large project by trying to integrate the code in grpc example helloworld directory: greeter_client.cc
I used the cmake option where assuming grpc is already installed in my system in $MY_INSTALL_DIR as described in grpc's document: cmake -DCMAKE_PREFIX_PATH=$MY_INSTALL_DIR
When I include it in my "large project", I changed the greeter_client.cc into .h and .cc file.
greeter_client.h
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
std::string SayHello(const std::string& user);
private:
std::unique_ptr<Greeter::Stub> stub_;
};
void libFun();
greeter_client.cc
#include <iostream>
#include <memory>
#include <string>
#include "greeter_client.h"
std::string GreeterClient::SayHello(const std::string& user) {
// the original implementation unchanged...
}
void libFun() {
GreeterClient client(grpc::CreateChannel(
"localhost:50051", grpc::InsecureChannelCredentials()));
client.SayHello("world");
}
and in the target destination (say the file is main.cc) I added
#include "/path/to/greeter_cient.h"
int main (){
libFun();
return 0;
}
The directory structure is
helloworld
greeter_client.h
greeter_client.cc
CMakeLists (the original one with little tweak to also include greeter_client.h in target greeter_client)
protos (the protos directory under examples in grpc project)
test
main.cc
CmakeList
The CMakeList for main.cc is like the following
cmake_minimum_required(VERSION 3.5.1)
project(test C CXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
# This part is copied from the grpc example CMakeFileList
set(protobuf_MODULE_COMPATIBLE TRUE)
find_package(Protobuf CONFIG REQUIRED)
message(STATUS "Using protobuf ${Protobuf_VERSION}")
set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)
# Find gRPC installation
# Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.
find_package(gRPC CONFIG REQUIRED)
message(STATUS "Using gRPC ${gRPC_VERSION}")
set(_GRPC_GRPCPP gRPC::grpc++)
add_subdirectory("../helloworld" "../helloworld")
add_executable(program "main.cc")
# THIS IS THE QUESTION: why adding ${_GRPC_GRPCPP} will work?
target_link_libraries(program greeter_client
${_GRPC_GRPCPP})
target_include_directories(program PRIVATE "../helloworld" )
The question is: initially, I did not add find_project(gRPC) in the main.cc 's CMakeList and I did not add ${_GRPC_GRPCPP} in the target_link_libraries of program target. And I will get error
complaining "/test/../helloworld/greeter_client.h:23:10: fatal error: 'grpcpp/grpcpp.h' file not found
#include <grpcpp/grpcpp.h>"
I read some threads and it seems that bracket include finds the files in system include paths. I am not sure why the grpc example can make it work by adding a dependency in target_link_libraries?
Another question is: ideally, I want main.cc does not care about anything inside greeter_client target. However, since I have to include greeter_client.h which in turn includes <grpcpp/grpcpp.h> I have to add the find_project and link the target in main.cc's CMakeList as well. How to avoid re-deal with this include <grpcpp/grpcpp.h> in main.cc's CMakeList?
Thanks!
If I understand you correctly, the real question here is
it seems that bracket include finds the files in system include paths.
I am not sure why the grpc example can make it work by adding a
dependency in target_link_libraries?
In short, #include <foo.h> will search system include paths first, but if that fails it will retry as if you wrote #include "foo.h".
Related
I have the following main.cpp, very simple script, trying to re-produce the problem and isolate to it's most basic.
#include<iostream>
#include<fmt/core.h>
// #include "json/json.hpp"
// #include <json/json.hpp>
// #include <nlohmann/json.hpp>
// #include "json.hpp"
// #include "nlohmann/json.hpp"
int main(){
fmt::print("Hello, world!\n");
return 0;
}
The commented out include statements are all of the paths I have tried to get this into my program.
My CMakeLists.txt file looks like this
cmake_minimum_required(VERSION 3.24)
project(main)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-std=c++17")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build)
# include(FetchContent)
# FetchContent_Declare(
# json
# GIT_REPOSITORY https://github.com/nlohmann/json
# )
# FetchContent_MakeAvailable(json)
include(FetchContent)
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt
GIT_TAG 9.0.0
)
FetchContent_MakeAvailable(fmt)
add_executable(main main.cpp)
# target_link_libraries(main json)
target_link_libraries(main fmt)
I've commented out the json part since it's not working obviously, I can also json-src and json-build in my _deps folder so I know for a fact that it is being downloaded into my local machine.
After running cmake CMakeLists.txt and make and then running the executable I get the error in the title 'nlohmann/json.hpp' file not found
Any help would be appreciated.
Tried to reproduce the example with another popular C++ package which worked fine. Tried changing the include statements to see if maybe I had something wrong since I don't fully understand all the nuance with CMake and am quite new to it.
You can either specifically use the interface target already included in the nlohmann library, which will automatically populate the correct include path for you, with:
target_link_libraries(main nlohmann_json::nlohmann_json)
Or you would need to specifically include the include path yourself:
include_directories(${json_SOURCE_DIR}/include)
With either way, you will be able to use #include <nlohmann/json.hpp> in your source.
Preparation
I added poco to my project using:
git clone --recurse-submodules https://github.com/pocoproject/poco.git ThirdParty/poco
So my project structure looks like this:
ThirdParty/poco
include/
src/
main.cpp
CMakeLists.txt
My CMakeLists looks something like this :
cmake_minimum_required(VERSION 3.13.4 FATAL_ERROR)
project(sample)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty/poco)
add_executable(runservice main.cpp)
target_link_libraries(runservice PUBLIC ${PROJECT_NAME} Poco::Net)
My main looks like this:
#include <iostream>
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPSClientSession.h>
using namespace std;
int main() {
//Code here
return 0;
}
Errors
I am able to include HTTPClientSession as <Poco/Net/HTTPClientSession.h> but when I include <Poco/Net/HTTPSClientSession.h>, it gives me the following error : fatal error: 'Poco/Net/HTTPSClientSession.h' file not found
Am I missing something in CMakeLists? I checked that HTTPSClientSession is not present in 'poco/Net', instead it's under 'poco/NetSSL_OpenSSL'.
So I tried to add Poco::NetSSL_OpenSSL to my target_include_libraries but then cmake is unable to generate build files correctly.
Any help would be really appreciated. Thank you for your time.
You need include_directories.
I'd also suggest to enclose the include paths in double quotes, rather than angle brackets.
But ... you'll be much better off starting with the cmake example, which will automagically take care of everything.
EDIT:
For cmake example:
target_link_libraries(pocoex PUBLIC Poco::Foundation Poco::XML Poco::JSON Poco::Util Poco::Net Poco::Crypto Poco::NetSSL)
I didn't know how to title this, it's quite unaccurate. Anyway here is the question:
I want to create a CMake project in Visual Studio that has to use glfw. However, I don't want to use the precompiled binaries, I want to compile glfw along with my application using the CMakeLists.txt file.
Here's my CMake file:
# CMakeList.txt : CMake project for BasicMandelbrotAnimation, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
project(BasicMandelbrotAnimation)
# Set the main file to main.cpp
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /ENTRY:mainCRTStartup")
# Include our different directories
include_directories(include)
include_directories(source)
# Include all source files in source directory
file(GLOB SOURCE source/*)
# Compile GLFW
add_subdirectory(extlibs/GLFW)
# CMake GLFW Settings
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
# Add source to this project's executable.
add_executable (${PROJECT_NAME} ${SOURCE})
target_link_libraries(${PROJECT_NAME} glfw)
find_package(OpenGL REQUIRED)
target_include_directories(${PROJECT_NAME} PUBLIC ${OPENGL_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} ${OPENGL_gl_LIBRARY})
target_link_libraries(${PROJECT_NAME} ${OPENGL_glu_LIBRARY})
# TODO: Add tests and install targets if needed.
The error I get is "Cannot open include file: 'unistd.h': No such file or directory" which is bugging me out because this is a UNIX file so how can I adapt the files to compile in windows?
Thank you.
EDIT:
This questions seemed like a duplicate, but isn't really. unistd.h is only the first problem, let's have a look at the problematic file:
#ifndef _glfw3_x11_platform_h_
#define _glfw3_x11_platform_h_
#include <unistd.h>
#include <signal.h>
#include <stdint.h>
#include <dlfcn.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xcursor/Xcursor.h>
// The XRandR extension provides mode setting and gamma control
#include <X11/extensions/Xrandr.h>
// The Xkb extension provides improved keyboard support
#include <X11/XKBlib.h>
// The Xinerama extension provides legacy monitor indices
#include <X11/extensions/Xinerama.h>
#if defined(_GLFW_HAS_XF86VM)
// The Xf86VidMode extension provides fallback gamma control
#include <X11/extensions/xf86vmode.h>
#endif
Here it is, first of all, unistdh is missing, I replace it with what was proposed in another post, but now it's the others that are missing, specifically dlfcn.h and X11 files and I don't know how to fix that.
Thank you.
EDIT2:
Forget what's inside x11_platform.h. The problem is in this line:
target_link_libraries(${PROJECT_NAME} glfw)
when doing this, cmake need x11_platform.h, that does not exist on windows. Does someone know how to skip this file or link another way?
Thank you.
I have a project in Clion using CMake and C++14. The project compiles but all standard library includes are marked as:
"Cannot find string", "Cannot find stdexcept", etc.
Additionally the symbols from the dll I included are not being detected. So they are all marked as:
"Cannot resolve ..."
I've included the header and cmakelist.txt. This is only happening in this project and I have almost identical cmakelist.txt files for all my projects. I have tried restarting CLion's cache. I also tried moving all the files to a new project which worked momentarily but with an hour CLion was flagging these lines again.
cmakelists.txt
cmake_minimum_required(VERSION 3.6)
project(BCI)
set(CMAKE_CXX_STANDARD 14)
#create dlls and executables in the root directory
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
include_directories(
${CMAKE_SOURCE_DIR}
)
set(SOURCE_FILES
NeuralInterface.hpp
)
add_library(BCI SHARED ${SOURCE_FILES})
set_target_properties(BCI PROPERTIES LINKER_LANGUAGE CXX)
NeuralInterface.hpp
#ifndef NEURALINTERFACE_HPP
#define NEURALINTERFACE_HPP
//c++ includes
#include <stdexcept> //these are the includes which cannnot be resolved
#include <string>
//project includes
#include "okFrontPanelDLL.h"
extern std::string IntanAcquire; //this says cannot resolve container std
...
#endif
What else can I do to CMake so it finds these headers?
I am trying to find the best way to link my project source code with my boost unit tests. I have a fairly basic project setup right now using CMake, however all examples of boost UTF that I have come across have shown very basic tests which do not touch source code in a project that is along side the tests.
As a minimal example I have the following:
CMakeLists.txt
cmake_minimum_required(version 2.8)
project(test-project)
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework )
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
add_subdirectory(src)
enable_testing()
add_subdirectory(test)
src/CMakeLists.txt
add_executable(example main.cpp foo.cpp)
src/foo.h
#include <string>
std::string hello(std::string name);
src/foo.cpp
#include "foo.h"
std::string hello(std::string name) { return "Hello " + name; }
src/main.cpp - Uses foo in a simple way
test/CMakeLists.txt
include_directories (../src)
set(TEST_REQUIRED_SOURCES ../src/foo.cpp)
add_executable (test test.cpp ${TEST_REQUIRED_SOURCES})
target_link_libraries(test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test(SimpleTest test)
test/test.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE SimpleTest
#include <boost/test/unit_test.hpp>
#include "foo.h"
BOOST_AUTO_TEST_CASE(ShouldPass) {
BOOST_CHECK_EQUAL(hello("fred"), "Hello fred")
}
While this works, I'd like to avoid the following:
Defining TEST_REQUIRED_SOURCES with a list of all of my files required to compile.
Avoiding the duplicate compilation of code.
Does my structure look correct for this sort of project? Would it make sense to compile my code under src into a library instead? Most of my experience with testing is from C# where this is much simpler.
You can have a look at how I did it there: https://github.com/NewbiZ/mengine/blob/master/CMakeLists.txt
Basically, I build an object file with my library, and reuse it in the main executable AND the tests. That way you only build once.
The interesting piece of CMake is:
# Just build the object files, so that we could reuse them
# apart from the main executable (e.g. in test)
ADD_LIBRARY(mengine_objects OBJECT ${MENGINE_SOURCES})
Then build the main executable:
ADD_EXECUTABLE(mengine $<TARGET_OBJECTS:mengine_objects>
src/main.cpp)
And the tests:
ADD_EXECUTABLE(test_tga $<TARGET_OBJECTS:mengine_objects>
test_tga.cpp)
Hope that helps!