I want to use protobuf in my C++ library. All dependencies so far are included using cmake's FetchContent module. I want to do the same with protobuf. However, I run into the following problem: Unknown CMake command "protobuf_generate_cpp". Any hints on how to solve this?
Excerpt of my CMakeLists.txt:
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 9.0.0)
FetchContent_Declare(protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
GIT_TAG v21.4)
FetchContent_MakeAvailable(fmt protobuf)
include_directories(${Protobuf_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS message.proto)
This works for me:
FetchContent_Declare(protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
GIT_TAG v21.4
SOURCE_SUBDIR cmake
FIND_PACKAGE_ARGS NAMES protobuf
)
FetchContent_MakeAvailable(protobuf)
On the consumer end do this
include(FindProtobuf)
find_package(protobuf CONFIG REQUIRED)
Note: This has only been tested on CMake v3.25
protobuf_generate_cpp is from FindProtobuf. It doesn't seem to work with a protoc that was build in the project with FetchContent. You'll have to call the protoc binary explicitly.
set(GENERATED_CODE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated)
set(PROTO_SRCS ${GENERATED_CODE_DIR}/message.pb.cc)
set(PROTO_HDRS ${GENERATED_CODE_DIR}/message.pb.h)
set(PROTOC ${protobuf_BINARY_DIR}/protoc)
set(PROTO_DIR ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_command(
OUTPUT ${PROTO_SRCS} ${PROTO_HDRS}
COMMAND ${PROTOC} --proto_path ${PROTO_DIR} message.proto --cpp_out ${GENERATED_CODE_DIR}
DEPENDS ${PROTOC} ${PROTO_DIR}/message.proto
)
Related
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.
I want to build a library libpng from source which requires libz which in turn I also want to build from source. I have one CMakeLists.txt file so far and the part that defines the build steps for both libraries looks like this:
if(NOT EXISTS ${CMAKE_BINARY_DIR}/build-zlib/build/libz.a)
file(DOWNLOAD https://www.zlib.net/zlib-1.2.11.tar.gz zlib.tar.gz TLS_VERIFY ON)
file(ARCHIVE_EXTRACT INPUT zlib.tar.gz)
include(ExternalProject)
ExternalProject_Add(zlib
SOURCE_DIR ${CMAKE_BINARY_DIR}/zlib-1.2.11
BINARY_DIR ${CMAKE_BINARY_DIR}/build-zlib/build
INSTALL_COMMAND cmake -E echo "Skipping install"
CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON
)
message(STATUS "zlib will be built during 'make'")
endif()
if(NOT EXISTS ${CMAKE_BINARY_DIR}/build-png/build/libpng.a)
include(ExternalProject)
ExternalProject_Add(png
GIT_REPOSITORY "https://github.com/glennrp/libpng.git"
GIT_TAG "v1.6.37"
BINARY_DIR ${CMAKE_BINARY_DIR}/build-png/build
INSTALL_COMMAND cmake -E echo "Skipping install"
CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON
)
message(STATUS "libpng will be built during 'make'")
endif()
There are two problems: First, CMake doesn't know that libz has to be built before libpng. Second, even if libz would be built before, CMake doesn't know that libz will be placed in ${CMAKE_BINARY_DIR}/build-zlib/build. I suppose the second problem may be fixed by adding list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR}/build-zlib/build) (please correct me if I'm wrong) but how do I deal with the first problem? Freely I've tried to add add_dependencies(png zlib) but libz is not getting built before libpng. The error message therefore states that libz can't be found:
CMake Error at /snap/cmake/876/share/cmake-3.20/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
I have to download zlib to use in my project.
I use externlproject_add() to downaload all zlib repository, build and install it.
After it, I want do install a lib that is part of zlib repository: minizip.
How to set this dependency on cmake?
zlib module:
cmake_minimum_required ( VERSION 2.8.7 )
include (ExternalProject)
if(UNIX)
# An external project for zlib
SET (GIT_URL https://github.com/madler/zlib.git)
SET (ZLIB_INSTALL ${CMAKE_CURRENT_BINARY_DIR})
SET (ZLIB_INCLUDE ${CMAKE_BINARY_DIR}/include/zlib)
SET (ZLIB_STATIC ${CMAKE_BINARY_DIR}/lib/libz.a )
SET (MINIZIP_DIR ${CMAKE_CURRENT_BINARY_DIR}/ZLIB/src/ZLIB/contrib/minizip)
ExternalProject_Add(zlib
PREFIX zlib
GIT_REPOSITORY ${GIT_URL}
INSTALL_DIR ${ZLIB_INSTALL}
PATCH_COMMAND ${CMAKE_COMMAND} -E remove <SOURCE_DIR>/zconf.h
BUILD_IN_SOURCE 1
PATCH_COMMAND ""
CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --includedir=${ZLIB_INCLUDE}
)
find_package(ZLIB REQUIRED)
if(ZLIB_FOUND)
add_subdirectory (${MINIZIP_DIR})
endif(ZLIB_FOUND)
SET (ZLIB_INCLUDE_DIR ${ZLIB_INSTALL}/include/zlib)
SET (ZLIB_LIBRARY "${ZLIB_INSTALL}")
ADD_LIBRARY (ZLIB_LIB STATIC IMPORTED DEPENDS zlib)
SET_TARGET_PROPERTIES (ZLIB_LIB PROPERTIES IMPORTED_LOCATION "${ZLIB_STATIC}")
endif(UNIX)
With this zlib module I have an error that following directory
/home/lais/Imagens/agent/build/ZLIB/src/ZLIB/contrib/minizip
doesn't exist yet when I run
cmake ..
And it's true. Doesn't exist yet. I should tell cmake it. But I don't know how to do it.
I solved it download a zip file that have minizip.
cmake_minimum_required ( VERSION 2.8.7 )
include (ExternalProject)
project (zlib)
if(UNIX)
# An external project for zlib
SET (URL http://www.winimage.com/zLibDll/unzip101e.zip)
SET (MINIZIP_INSTALL ${CMAKE_CURRENT_BINARY_DIR})
SET (MINIZIP_STATIC ${CMAKE_BINARY_DIR}/lib/minizip.a )
message ("zlib = ${zlib}")
ExternalProject_Add(minizip
DEPENDS zlib
PREFIX minizip
URL ${URL}
INSTALL_DIR ${MINIZIP_INSTALL}
BUILD_IN_SOURCE make
CONFIGURE_COMMAND ""
)
SET (MINIZIP_LIBRARY "${MINIZIP_INSTALL}")
ADD_LIBRARY (MINIZIP_LIB STATIC IMPORTED DEPENDS minizip, zlib)
SET_TARGET_PROPERTIES (MINIZIP_LIB PROPERTIES IMPORTED_LOCATION "${MINIZIP_STATIC}")
endif(UNIX)
I have an application with a mildly complicated build process, and as a bit of a newb to CMake, I was wondering if anyone could provide me with any pointers.
At preset, the application consists of a single executable, built from a source tree provided in the src and include folders.
It requires a few libraries to work, the big ones being Boost and Python. Python is embedded in the application, and Boost requires knowledge of the custom python install at compile time. I also use Qt, but I'm just linking against the system Qt for this.
What I'd like to have at the end is a stage folder, containing the compiled executable, and a lib folder with the required boost and python libraries.
At present, I have a single CMakeLists.txt file, and I am using ExternalProject to build Boost and Python from bzipped tarballs of their source. It gets a little messy where I copy out the compiled libs from the prefixed install directories.
Things are working, but I have a feeling I'm doing things very backwards. I sometimes see multiple CMakeLists in nested subdirectories but don't know how they would relate to my project. Would anyone who has worked on similarly scoped projects be able to weigh in and give me some pointers?
I should add that I hope to include Windows as a platform in the near future, and that things are currently running on Linux.
Note: This is my current CMakeLists.txt, I realise that boost isn't configured and that things aren't fully moved to the stage folder. I have been doing this manually, but I wanted to ask before I dig myself much deeper :)
Thanks!
CmakeList.txt
cmake_minimum_required(VERSION 2.6)
set(CMAKE_BUILD_TYPE Debug)
set(PROJ_NAME "mwave")
project(${PROJ_NAME})
include_directories("include")
include(ExternalProject)
# Add cmake dir to cmake module path so custom find modules will work
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
#Build Python via External Project
ExternalProject_Add(
Python
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/python
URL ${CMAKE_CURRENT_SOURCE_DIR}/extern/Python-3.3.0.tar.bz2
URL_MD5 2dbff60afed2b5f66adf6f77dac9e139
UPDATE_COMMAND ""
CONFIGURE_COMMAND ./configure -q --prefix=${CMAKE_CURRENT_BINARY_DIR}/external/python --enable-shared
BUILD_COMMAND make
BUILD_IN_SOURCE 1
INSTALL_COMMAND make install
)
# Manually copy the compiled python files and dirs to our stage folder
add_custom_command(TARGET Python PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_BINARY_DIR}/external/python/lib/pkgconfig
${CMAKE_CURRENT_BINARY_DIR}/stage/lib/pkgconfig)
add_custom_command(TARGET Python PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_BINARY_DIR}/external/python/lib/python3.3
${CMAKE_CURRENT_BINARY_DIR}/stage/lib/python3.3)
add_custom_command(TARGET Python PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/external/python/lib/libpython3.so
${CMAKE_CURRENT_BINARY_DIR}/stage/lib/libpython3.so)
add_custom_command(TARGET Python PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/external/python/lib/libpython3.3m.so.1.0
${CMAKE_CURRENT_BINARY_DIR}/stage/lib/libpython3.3m.so.1.0)
add_custom_command(TARGET Python PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
libpython3.3m.so.1.0
${CMAKE_CURRENT_BINARY_DIR}/stage/lib/libpython3.3m.so)
#Python
set(PYTHON_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/external/python/include/python3.3m")
set(PYTHON_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/external/python/lib/libpython3.3m.so" "pthread" "m" "util" "readline")
#Build boost via External Project
ExternalProject_Add(
Boost
DEPENDS Python
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/external/boost
URL ${CMAKE_CURRENT_SOURCE_DIR}/extern/boost_1_51_0_mwave.tar.bz2
URL_MD5 fe203a243e451b4dd4754c7b283b1db9
UPDATE_COMMAND ./bootstrap.sh --with-libraries=python,system,thread,program_options
CONFIGURE_COMMAND ""
BUILD_COMMAND ./b2
BUILD_IN_SOURCE 1
INSTALL_COMMAND ""
)
#Boost (workaround until external project is working)
set(Boost_INCLUDE_DIRS "/opt/mwave/include")
set(Boost_LIBRARIES "/opt/mwave/lib/libboost_python3.so" "/opt/mwave/lib/libboost_program_options.so")
#OpenImageIO
set(OIIO_PATH "/opt/mwave/oiio/dist/linux64.debug")
find_package(OIIO REQUIRED)
#Qt4
find_package(Qt4 REQUIRED)
set(QT_USE_QTOPENGL TRUE)
include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
#OpenGL
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
# Mwave app
set(HEADERS
"include/Application.h"
"include/ImageChannel.h"
"include/CompDag.h"
"include/Dag.h"
"include/Gui/DagView.h"
"include/Gui/DagScene.h"
"include/Gui/MainWindow.h"
"include/Gui/GLViewer.h"
"include/Gui/Nodes/GNodeEdge.h"
"include/Gui/Nodes/GNodeLabel.h"
"include/Gui/Nodes/GNodeCacheStatus.h"
"include/Gui/Nodes/GNode.h"
"include/Gui/Nodes/GRead.h"
"include/Gui/Nodes/GViewer.h"
"include/MwaveException.h"
"include/Nodes/Node.h"
"include/Nodes/Read.h"
"include/Nodes/Viewer.h"
"include/mwave.h"
"include/main.h"
"include/shaders.h"
)
set(QOBJECT_HEADERS
"include/Gui/QCompDag.h"
"include/Gui/QPythonEditor.h"
"include/Gui/ViewerWidget.h"
)
set(SOURCES
"src/Application.cpp"
"src/CompDag.cpp"
"src/main.cpp"
"src/mwave.cpp"
"src/Dag.cpp"
"src/Gui/DagView.cpp"
"src/Gui/DagScene.cpp"
"src/Gui/MainWindow.cpp"
"src/Gui/QPythonEditor.cpp"
"src/Gui/GLViewer.cpp"
"src/Gui/ViewerWidget.cpp"
"src/Gui/Nodes/GNode.cpp"
"src/Gui/Nodes/GNodeEdge.cpp"
"src/Gui/QCompDag.cpp"
"src/Nodes/Node.cpp"
"src/Nodes/Read.cpp"
"src/Nodes/Viewer.cpp"
)
QT4_WRAP_CPP(HEADERS_MOC ${QOBJECT_HEADERS})
## Compiler flags
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-O2") ## Optimize
set(CMAKE_CXX_FLAGS "-O3") ## Optimize More
endif()
include_directories(${PYTHON_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
${GLEW_INCLUDE_PATH}
${OPENGL_INCLUDE_DIR}
${OIIO_INCLUDE_DIR}
)
add_executable(mwave WIN32 ${HEADERS} ${HEADERS_MOC} ${SOURCES})
set_target_properties(mwave PROPERTIES OUTPUT_NAME mwave.bin)
target_link_libraries( mwave
${PYTHON_LIBRARIES}
${Boost_LIBRARIES}
${OIIO_LIBRARIES}
${GLEW_LIBRARY}
${OPENGL_LIBRARIES}
${QT_LIBRARIES})
cmake 2.6, which you are using, does not support ExternalProjects.
ExternalProjects are supported in cmake 2.8 series. Please move to cmake 2.8.
The below link clarifies
http://www.cmake.org/pipermail/cmake/2011-June/044993.html
I'm trying to build libpng with CMAKE, but it requires zlib, so I'm trying to build them both but not having any luck. I like FetchContent so I can specify a GIT_TAG and easily update that in the future if needed. For now I have just a blank test.c file to illustrate the problem.
I get these link errors:
LNK1120 1 unresolved externals
MinimalApp\out\build\x64-Debug\_deps\libpng-build\png-fix-itxt.exe
LNK2019 unresolved external symbol crc32 referenced in function main
When I build with this CMakeLists.txt
cmake_minimum_required (VERSION 3.14)
include(FetchContent)
project(MinimalApp)
FetchContent_Declare(
zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.2.11
)
FetchContent_MakeAvailable(zlib)
set(ZLIB_INCLUDE_DIR ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})
set(PNG_BUILD_ZLIB ON CACHE BOOL "Custom zlib Location, else find_package is used")
FetchContent_Declare(
libpng
GIT_REPOSITORY https://github.com/glennrp/libpng.git
GIT_TAG v1.6.37
)
FetchContent_MakeAvailable(libpng)
include_directories(
${libpng_SOURCE_DIR}
${libpng_BINARY_DIR}
)
add_library(MinimalApp SHARED
"test.c"
)
set_target_properties(MinimalApp PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../bin/${CMAKE_BUILD_TYPE}/x64
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/../bin/${CMAKE_BUILD_TYPE}/x64
)
My test.c file is blank.
I ran into this problem recently and I believe you also need to set the ZLIB_LIBRARY cmake variable. libpng expects this variable to be set if you are using PNG_BUILD_ZLIB.
This can be as simple as:
set(ZLIB_LIBRARY zlib)