*.pb.h and *.pb.cc protobuf files not getting generated - cmake

I am using protobuf_generate_cpp() in order to generate *.cc and *.h files from the *.proto file but it is not getting executed. I do not get any error message, the lines are just skipped. The CMakeLists.txt file looks something like this:
cmake_minimum_required(VERSION 3.1.2)
cmake_policy(SET CMP0028 NEW)
project(ProjectName CXX C)
execute_process(COMMAND conan install . WORKING_DIRECTORY ${CMAKE_HOME_DIRECTORY})
include(conanbuildinfo.cmake)
conan_basic_setup(TARGETS)
find_package(Protobuf REQUIRED)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS /path/to/NAME.proto)
add_custom_command(
OUTPUT NAME.pbs.h
OUTPUT NAME.pbs.cc
DEPENDS NAME.proto
COMMAND protoc --cpp_out=$(CMAKE_BINARY_SOURCE_DIR) --proto_path=../path/to/NAME.proto
)
set(ProjectName-HeaderFiles
${ProjectName-HeaderFiles}
<list of all header files>
)
set(ProjectName-SourceFiles
${ProjectName-SourceFiles}
<list of all source files>
)
add_executable(ProjectName ${PROTO_SRCS} ${PROTO_HDRS}
<list of all other executables>
)
add_definitions(
-D_CONSOLE
-DWIN32
-D_DEBUG
-DSTANDALONE_PROGRAM
)
include_directories(
<list of all include paths>
)
target_link_libraries( ProjectName
PUBLIC
CONAN_PKG::Protobuf
LIB1
LIB2
)
My solution is created #location CMAKE_BINARY_SOURCE_DIR but NAME.pb.h and NAME.pb.cc files do not get created. Could someone let me know what the issue might be? Any suggestions are appreciated.

Related

CMake - How to get include directories of external project?

I tried to used https://github.com/julianxhokaxhiu/SteamworksSDKCI to use steam api on a simple SFML application (helloworld).
I wanted to use cmake to learn it, but I am struggling to understand how the provided CMakeLists and Find*.cmake file are expected to be used.
Currently, I have modified the CMakeLists to change the INSTALL_DIR
INSTALL_DIR "${CMAKE_BINARY_DIR}/../../vendor"
and my CMakeLists is :
cmake_minimum_required(VERSION 3.19)
project(SfmlWithCMake VERSION 1.0)
include(FetchContent)
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake_steam")
# Configure external project
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam)
execute_process(
COMMAND ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/cmake_steam
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/cmake_steam
)
# Build external project
execute_process(
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR}/cmake_steam
)
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
find_package(STEAMWORKSSDK REQUIRED)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
# Generate config.h
configure_file(config.h.in config.h)
add_executable(
SfmlWithCMake
main.cpp
)
get_target_property(STEAMSDK STEAMWORKSSDK::STEAMWORKSSDK INCLUDE_DIRECTORIES)
target_include_directories(
SfmlWithCMake
PRIVATE
"${PROJECT_BINARY_DIR}"
"${STEAMSDK}"
)
target_link_libraries(
SfmlWithCMake
sfml-graphics
STEAMWORKSSDK::STEAMWORKSSDK
-static gcc stdc++ winpthread -dynamic
)
install(TARGETS SfmlWithCMake DESTINATION bin)
How to get include directories?
I do not succeed to add the steam include to the target_include_directories.
Here the ${STEAMSDK} is my last attempt to get the directory.
If I replace this by ${PROJECT_BINARY_DIR}/vendor/include, everything works.
Also, why does the SFML include are automatically added to my target include directories and not the steam one?
Am I using the Find*.cmake file the right way?
I understood that ExternalProject_Add was performed at build time and thus, as the find_package is needed at configue time, I added the two "execute_process". But, the readme on github only says to do the find package and add the target to target_link_libraries...
Thanks.

CLion parses GCC errors?

I have a few CMake targets in my project that calls makefiles, which will call gcc.
When there is a build error it shows up on Messages>Build:
my_dir/my_file.c: In function 'my_func':
my_dir/my_file.c.c:52:5: error: expected ';' before '}' token
I wanted to click on it and go straight to my_dir/my_file.c.c:52:5, is that possible?
My Cmakelists.txt only has symbols and include folders for indexing purposes, no C build configuration since all of that is made in the makefiles.
EDIT
This is my CMakeLists.txt structure:
cmake_minimum_required(VERSION 3.7)
project(myexec)
set(CMAKE_CXX_STANDARD 99)
set(MakefileDir ${CMAKE_CURRENT_SOURCE_DIR}/make)
add_custom_target(
mytarget
ALL
WORKING_DIRECTORY ${MakefileDir}
COMMAND make all)
file(GLOB_RECURSE SRCS *.c)
file(GLOB_RECURSE HDRS *.h)
include_directories(
sometthing/inc
(...)
)
add_definitions(
-DMY_SYM=1
(...)
)
add_executable(myexec EXCLUDE_FROM_ALL ${SRCS} ${HDRS})

How to reload cmake targets

Following is the my scenario. I have one top level CMakeList.txt and another 2 internal CMakeList.txt. In top level cmake I have 3 custom targets that are copy, build, copyandbuild. As name specifies make copy copies the source directories (i.e dir1, dir2) to ${CMAKE_SOURCE_DIR}. make build creates libs and executables. make copyandbuild (copy+build).
Running cmake .. from build directory completes successfully.
If I run make copyandbuild it is copying to ${CMAKE_SOURCE_DIR} but at the time of build it is showing error that
No rule to make target `dir1/libmylib.so', needed by `CMaketargetdbuild'. Stop
MyProject
dir1
CMakeLists.txt
dir2
CMakeLists.txt
CMakeLists.txt
It is working if i execute commands in below order.
cmake ..
make copyandbuild
cmake ..
make build
My requirement is it should work with out running cmake and make build again as copyandbuild doing the same work.
Top level CMakeLists.txt:
cmake_minimum_required(VERSION 2.6)
cmake_minimum_required(VERSION 2.6)
set(RE_BUILD make rebuild_cache)
set(OUTPUT_DIR ${CMAKE_SOURCE_DIR}/../)
if(EXISTS ${CMAKE_SOURCE_DIR}/dir1)
message(WARNING "Found dir1 dir")
add_subdirectory(dir1 EXCLUDE_FROM_ALL)
else()
message(WARNING "Couldn't find dir1 directory ")
endif()
if(EXISTS ${CMAKE_SOURCE_DIR}/dir2)
add_subdirectory(dir2 EXCLUDE_FROM_ALL)
else()
message(WARNING "Couldn't find dir2 directory")
endif()
set(MOVE_LIB_COMMAND mv src/myapp . && mv dir1/mylib .)
set(COPY_COMMAND cp -r ../sourceCode1 ../dir1 && cp -r ../sourceCode2 ../dir2)
set(CLEAN_DIR1_COMMAND cmake -E remove_directory ${CMAKE_SOURCE_DIR}/dir1)
set(CLEAN_DIR2_COMMAND cmake -E remove_directory ${CMAKE_SOURCE_DIR}/dir2)
set(SET_SLEEP sync)
#Copy command
add_custom_target(
copy ${COPY_COMMAND}
COMMAND ${RE_BUILD}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
#Compilation
add_custom_target(
build
COMMAND ${MOVE_LIB_COMMAND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS mylib myapp
)
#copy and compile
add_custom_target(
copyandbuild
COMMAND ${MOVE_LIB_COMMAND}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS copy mylib myapp
)
add_custom_command(TARGET copy POST_BUILD
COMMAND ${SET_SLEEP}
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
dir1 CMake is :
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
include_directories(
${MY_APP_INCLUDE_DIRS}
)
link_directories(
${MY_APP_LIBDIR}
)
add_library(mylib
SHARED
com/*.cpp
)
target_link_libraries(mylib myapp_lib)
dir2 CMake is :
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
include_directories(
${MY_APP_INCLUDE_DIRS}
)
link_directories(
${MY_APP_LIBDIR}
)
You are using CMake in a way that prevents its proper function. By explicitly invoking shell commands in many places, when you could use CMake built in features, you are robbing CMake of any context that it could use to build your programs. Also, using wildcards like *.cpp in CMake is considered bad practice. And you have a number of duplicate statements--you do not need cmake_minimum_required() or setting compiler flags other than at the top level.
In short, your CMakeLists.txt at the top level should look more like this:
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++11")
add_subdirectory(dir1 EXCLUDE_FROM_ALL)
You should not need to copy source files around--just build them from where they are, for example your dir1/CMakeLists.txt might be:
add_library(mylib
SHARED
sourceCode1/mylib.cpp
)
Keep it simple. Get it working. Then ask questions if you need to add missing features.

PROTOBUF_GENERATE_CPP not generating src and header files

My cmake configuration is not generating any protobuf src and header files.
I've already checked if the proto files can be found.
Cmakelists.txt
cmake_minimum_required(VERSION 3.0.2)
..
include(FindProtobuf REQUIRED)
file(GLOB PROTO_DEF "${CMAKE_CURRENT_SOURCE_DIR}/protobuf/*/*.proto")
foreach(file ${PROTO_DEF})
if(EXISTS ${file})
MESSAGE("YES")
else()
MESSAGE("NO")
endif()
endforeach()
SET(PROTOBUF_GENERATE_CPP_APPEND_PATH PROTOBUF)
SET(PROTOBUF_PROTOC_EXECUTABLE protoc.exe)
..
PROTOBUF_GENERATE_CPP(PROTO_SRC PROTO_INCL ${PROTO_DEF})
..
add_library(${PROJECT_NAME} STATIC ${INCLUDES} ${INTERNAL_INCLUDES} ${SRC} ${PROTO_SRC} ${PROTO_INCL})
target_link_libraries(${PROJECT_NAME} ${PROTOBUF_LIBRARIES})
I have checked the FindProtobuf.cmake and half way through:
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
MESSAGE(1 ${CMAKE_CURRENT_BINARY_DIR})
MESSAGE(2 ${_protobuf_include_path})
MESSAGE(3 ${ABS_FIL})
MESSAGE(4 ${PROTOBUF_PROTOC_EXECUTABLE})
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM )
endforeach()
You can see i've added the 4 message commands, the script reaches this point and variables show good values.
The proto files do have a depencency to the library, thus the command should get executed !?
Any ideas on this problem?
update
replacing the add_custom_command with
EXEC_PROGRAM(${PROTOBUF_PROTOC_EXECUTABLE} ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
does generate the source and header files, must i manually activate the custom_commmands?
Regards Auke
The add_custom_command is fired (for my project) during compilation time.
Adding
SET_SOURCE_FILES_PROPERTIES(${PROTO_SRC} ${PROTO_INCL} PROPERTIES GENERATED TRUE)
gives cmake info that the files will be generated.
Alternative if you have an external proto folder:
file(GLOB PROTOBUF_FILELIST ${PROTO_INCLUDE_DIR}/*.proto)
foreach( proto_file ${PROTOBUF_FILELIST} )
get_filename_component(proto_name ${proto_file} NAME_WE)
get_filename_component(proto_path ${PROTO_INCLUDE_DIR} ABSOLUTE)
set_source_files_properties("${proto_path}/${proto_name}.pb.cc"
"${proto_path}/${proto_name}.pb.h"
PROPERTIES GENERATED TRUE)
endforeach()
See that:
https://cmake.org/cmake/help/v3.20/module/FindProtobuf.html
Example:
find_package(Protobuf REQUIRED)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS foo.proto)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS EXPORT_MACRO DLL_EXPORT foo.proto)
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS DESCRIPTORS PROTO_DESCS foo.proto)
protobuf_generate_python(PROTO_PY foo.proto)
add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
target_link_libraries(bar ${Protobuf_LIBRARIES})
Note The protobuf_generate_cpp and protobuf_generate_python functions and add_executable() or add_library() calls only work properly within the same directory.
This problem only happens when the target is a library (using add_library, add_executable seems to be fine). The PROTOBUF_GENERATE_CPP will defer the generation of protobuf sources and headers when building the library. A workaround is to define a custom target and add it as a dependency to the lib target. e.g.
add_custom_target(proto_dep DEPENDS ${PROTO_SRCS} ${PROTO_HDRS})
add_library(${PROJECT_NAME} STATIC ${OTHER_SRCS})
add_dependencies(${PROJECT_NAME} proto_dep)
target_link_libraries(${PROJECT_NAME} PRIVATE gRPC::grpc++ gRPC::grpc++_reflection protobuf::libprotobuf)

CPack create packages with executables from different source tree

The problem is as follows:
Project structure:
ProjectDir
- CMakeLists.txt
- src
-- CMakeLists.txt
-- FirstApp
--- CMakeLists.txt
--- ... sources ...
-- SecondApp
--- CMakeLists.txt
--- ... sources ...
- tools
-- CMakeLists.txt
-- SomeTool
--- CMakeLists.txt
--- ... sources ...
-- SomeOtherTool
--- CMakeLists.txt
--- ... sources ...
What I want to achieve is:
package (let it be rpm or deb) with SomeTool binaries;
package with FirstApp, SecondApp AND SomeOtherTool binaries;
As far as I know:
CPack is putting into packages content the stuff that is defined in install command;
CPack cannot be called ( include(CPack) ) twice in the same tree (for example it cannot be called in CMakeLists.txt at src level AND SecondApp level);
What do I have
In ProjectDir/tools/SomeTool/CMakeLists.txt I've (it's pseado code):
PROJECT( SomeTool )
SET(TARGET SomeTool)
SET(CPACK_GENERATOR "RPM")
SET(CPACK_PACKAGE_NAME "SomeTool")
# ...
# all the other CPACK_* stuff
# ...
include(CPack)
add_custom_target(${TARGET}-package
COMMAND cpack --config "${CMAKE_CURRENT_BINARY_DIR}/CPack${PROJECT_NAME}Config.cmake")
SET(SOURCES ...)
SET(HEADERS ...)
add_executable(${TARGET} ${SOURCES} ${HEADERS})
install(TARGETS ${TARGET}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/bin)
This way I can call make SomeTool-package and it'll create package (SomeTool.rpm) with content /usr/bin/SomeTool. Great!
I can have very similar CMakeLists.txt in ProjectDir/src/ dir:
# src/CMakeLists.txt
PROJECT( MainProject )
SET(CPACK_GENERATOR "RPM")
SET(CPACK_PACKAGE_NAME "MainProject")
# ...
# all the other CPACK_* stuff
# ...
include(CPack)
add_custom_target(MainProject-package
COMMAND cpack --config "${CMAKE_CURRENT_BINARY_DIR}/CPack${PROJECT_NAME}Config.cmake")
add_subdirectory(FirstApp)
add_subdirectory(SecondApp)
# src/FirstApp/CMakeLists.txt
SET(TARGET FirstApp)
SET(SOURCES ...)
SET(HEADERS ...)
add_executable(${TARGET} ${SOURCES} ${HEADERS})
install(TARGETS ${TARGET}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/bin)
# src/SecondApp/CMakeLists.txt
SET(TARGET SecondApp)
SET(SOURCES ...)
SET(HEADERS ...)
add_executable(${TARGET} ${SOURCES} ${HEADERS})
install(TARGETS ${TARGET}
RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/bin)
This way I can call make MainProject-package and it'll create package (MainProject.rpm) with content /usr/bin/FirstApp and /usr/bin/SecondApp. Great!
SomeOtherTool also have a CMakeLists.txt which looks the same as FirstApp and SecondApp CMakeLists.txt and I can call make SomeOtherTool and it'll produce SomeOtherTool binaries.
The Question
As CPack is puting into packages stuff connected to install command, how can I connect SomeOtherTool with my MainProject-package ?
My solution would (is) be to put another install clause at the end of src/CMakeLists.txt that'd look like:
add_dependency(MainProject SomeOtherTool)
install(FILES ${CMAKE_BINARY_DIR}/SomeOtherTool DESTINATION ${CMAKE_INSTALL_PREFIX}/usr/bin )
Is there any other way? This solution doesn't look clean.. If I change the SomeOtherTool executable name I'll have to change it in here also. The same goes with install path.