Skip to content

Commit

Permalink
Make sure to export the FindProtobuf config after using FetchContent.…
Browse files Browse the repository at this point in the history
… Build protoc from scratch.
  • Loading branch information
fruffy committed Nov 27, 2023
1 parent ab11c7f commit 93dd245
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 52 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ if (BUILD_STATIC_RELEASE)
# Set the static variable
set(P4C_STATIC_BUILD STATIC)
# Do not bring in dynamic libstdcc and libgcc
set(CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++ -Wl,-z,muldefs")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++ -Wl,-z,muldefs")
add_definitions(-DP4C_STATIC_BUILD)
endif ()

Expand Down
2 changes: 1 addition & 1 deletion backends/dpdk/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ add_custom_target (dpdk_runtime_dir
# placed in the build directory inside `control-plane` directory
add_custom_command(
OUTPUT ${DPDK_P4RUNTIME_INFO_GEN_SRCS} ${DPDK_P4RUNTIME_INFO_GEN_HDRS}
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
--proto_path ${DPDK_P4RUNTIME_DIR}
--proto_path ${P4RUNTIME_STD_DIR}
--cpp_out ${CMAKE_CURRENT_BINARY_DIR}/p4/config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ function(validate_protobuf testfile testfolder)
file(APPEND ${testfile} "for item in \${txtpbfiles[@]}\n")
file(APPEND ${testfile} "do\n")
file(APPEND ${testfile} "\techo \"Found \${item}\"\n")
file(APPEND ${testfile} "\t${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${CMAKE_CURRENT_LIST_DIR}/../proto --proto_path=${P4RUNTIME_STD_DIR} --proto_path=${P4C_SOURCE_DIR}/control-plane --encode=p4testgen.TestCase p4testgen.proto < \${item}\n")
file(
APPEND ${testfile}
"\t${PROTOC_BINARY} -I${CMAKE_CURRENT_LIST_DIR}/../proto -I${Protobuf_INCLUDE_DIR} -I${P4RUNTIME_STD_DIR} -I${P4C_SOURCE_DIR}/control-plane --encode=p4testgen.TestCase p4testgen.proto < \${item}\n"
)
file(APPEND ${testfile} "done\n")
endfunction(validate_protobuf)

Expand Down
122 changes: 76 additions & 46 deletions cmake/Protobuf.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,75 @@ macro(p4c_obtain_protobuf)
endif()
find_package(Protobuf CONFIG)
if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED)
find_package(Protobuf REQUIRED)
endif()
# Backwards compatibility
# Define camel case versions of input variables
foreach(UPPER
PROTOBUF_SRC_ROOT_FOLDER
PROTOBUF_IMPORT_DIRS
PROTOBUF_DEBUG
PROTOBUF_LIBRARY
PROTOBUF_PROTOC_LIBRARY
PROTOBUF_INCLUDE_DIR
PROTOBUF_PROTOC_EXECUTABLE
PROTOBUF_LIBRARY_DEBUG
PROTOBUF_PROTOC_LIBRARY_DEBUG
PROTOBUF_LITE_LIBRARY
PROTOBUF_LITE_LIBRARY_DEBUG
)
if (DEFINED ${UPPER})
string(REPLACE "PROTOBUF_" "Protobuf_" Camel ${UPPER})
if (NOT DEFINED ${Camel})
set(${Camel} ${${UPPER}})
endif()
endif()
endforeach()
# Protobuf sets the protoc binary to a generator expression, which are highly problematic.
# They are problematic because they are basically evaluated at build time.
# However, we may have scripts that depend on the actual build time during the configure phase.
# Hard code a custom binary instead.
find_program(PROTOC_BINARY protoc)

if(ENABLE_PROTOBUF_STATIC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
set(PROTOBUF_LIBRARY "protobuf::libprotobuf")
set(PROTOBUF_PROTOC_EXECUTABLE "protobuf::protoc")
else()
# Google introduced another breaking change with protobuf 22.x by adding abseil as a new
# dependency. https://protobuf.dev/news/2022-08-03/#abseil-dep We do not want abseil, so we stay
# with 21.x for now.
set(P4C_PROTOBUF_VERSION "21.12")
message("Fetching Protobuf version ${P4C_PROTOBUF_VERSION} for P4C...")

# Unity builds do not work for Protobuf...
set(CMAKE_UNITY_BUILD_PREV ${CMAKE_UNITY_BUILD})
set(CMAKE_UNITY_BUILD OFF)
# Print out download state while setting up Protobuf.
set(FETCHCONTENT_QUIET_PREV ${FETCHCONTENT_QUIET})
set(FETCHCONTENT_QUIET OFF)
# Build Protobuf with position-independent code.
set(CMAKE_POSITION_INDEPENDENT_CODE_PREV ${CMAKE_POSITION_INDEPENDENT_CODE})
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(protobuf_BUILD_TESTS OFF CACHE BOOL "Build tests.")
set(protobuf_BUILD_PROTOC_BINARIES OFF CACHE BOOL "Build libprotoc and protoc compiler.")
set(protobuf_BUILD_PROTOC_BINARIES ON CACHE BOOL "Build libprotoc and protoc compiler.")
# Only ever build the static library. It is not safe to link with a local dynamic version.
set(protobuf_BUILD_SHARED_LIBS OFF CACHE BOOL "Build Shared Libraries")
# Unity builds do not work for Protobuf...
set(SAVED_CMAKE_UNITY_BUILD ${CMAKE_UNITY_BUILD})
set(CMAKE_UNITY_BUILD OFF)
# This is necessary to be able to call FindPackage.
set(protobuf_INSTALL ON CACHE BOOL "Install Protobuf")
# Derive the target architecture in order to build the right architecture.
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL
"arm64"
)
set(protobuf_ARCH "aarch_64")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL
"amd64"
)
set(protobuf_ARCH "x86_64")
else()
message(FATAL_ERROR "Unsupported host architecture `${CMAKE_HOST_SYSTEM_PROCESSOR}`")
endif()

fetchcontent_declare(
protobuf
URL https://github.com/protocolbuffers/protobuf/releases/download/v${P4C_PROTOBUF_VERSION}/protobuf-cpp-3.${P4C_PROTOBUF_VERSION}.tar.gz
Expand All @@ -45,49 +90,34 @@ macro(p4c_obtain_protobuf)
GIT_PROGRESS TRUE
)

# Derive the target architecture in order to download the right zip.
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
set(protobuf_ARCH "aarch_64")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "amd64")
set(protobuf_ARCH "x86_64")
else()
MESSAGE(FATAL_ERROR "Unsupported host architecture `${CMAKE_HOST_SYSTEM_PROCESSOR}`")
endif()

# Pull a different protoc binary for MacOS.
# TODO: Should we build from scratch?
if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
fetchcontent_declare(
protoc
URL https://github.com/protocolbuffers/protobuf/releases/download/v${P4C_PROTOBUF_VERSION}/protoc-${P4C_PROTOBUF_VERSION}-osx-${protobuf_ARCH}.zip
USES_TERMINAL_DOWNLOAD TRUE
GIT_PROGRESS TRUE
)
else()
fetchcontent_declare(
protoc
URL https://github.com/protocolbuffers/protobuf/releases/download/v${P4C_PROTOBUF_VERSION}/protoc-${P4C_PROTOBUF_VERSION}-linux-${protobuf_ARCH}.zip
USES_TERMINAL_DOWNLOAD TRUE
GIT_PROGRESS TRUE
)
endif()

fetchcontent_makeavailable(protoc)
# Exclude Protobuf from the main make install step. We only want to use it locally.
fetchcontent_makeavailable_but_exclude_install(protobuf)

# Reset unity builds to the previous state...
set(CMAKE_UNITY_BUILD ${SAVED_CMAKE_UNITY_BUILD})
set(FETCHCONTENT_QUIET ${FETCHCONTENT_QUIET_PREV})

set(PROTOBUF_PROTOC_EXECUTABLE ${protoc_SOURCE_DIR}/bin/protoc CACHE STRING
"Protoc executable."
)
set(Protobuf_INCLUDE_DIR ${protobuf_SOURCE_DIR}/src/ CACHE STRING "Protobuf include directory.")
set(PROTOBUF_LIBRARY libprotobuf)
# Protobuf source code may trigger warnings which we need to ignore.
# Protobuf and protoc source code may trigger warnings which we need to ignore.
set_target_properties(libprotobuf PROPERTIES COMPILE_FLAGS "-Wno-error")
set_target_properties(libprotoc PROPERTIES COMPILE_FLAGS "-Wno-error")

# Add the Protobuf directory to our module path for module builds.
list(APPEND CMAKE_MODULE_PATH "${protobuf_BINARY_DIR}/cmake/protobuf")

# Set some Protobuf variables manually until we are able to call FindPackage directly.
set(Protobuf_FOUND TRUE)
set(Protobuf_LIBRARY "protobuf::libprotobuf")
set(Protobuf_PROTOC_LIBRARY "protobuf::libprotoc")
set(Protobuf_PROTOC_EXECUTABLE $<TARGET_FILE:protoc>)
# Protobuf sets the protoc binary to a generator expression, which are highly problematic.
# They are problematic because they are basically evaluated at build time.
# However, we may have scripts that depend on the actual build time during the configure phase.
# Hard code a custom binary instead.
set(PROTOC_BINARY ${protobuf_BINARY_DIR}/protoc)
set(Protobuf_INCLUDE_DIR "${protobuf_SOURCE_DIR}/src/")

message("Done with setting up Protobuf for P4C.")
# Reset temporary variable modifications.
set(CMAKE_UNITY_BUILD ${CMAKE_UNITY_BUILD_PREV})
set(FETCHCONTENT_QUIET ${FETCHCONTENT_QUIET_PREV})
set(CMAKE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE_PREV})
endif()


message("Done with setting up Protobuf for P4C.")
endmacro(p4c_obtain_protobuf)
6 changes: 3 additions & 3 deletions control-plane/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ set (P4RUNTIME_GEN_PYTHON "control-plane")
add_custom_target (mkP4configdir
${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/p4/config)
add_custom_command(OUTPUT ${P4RUNTIME_GEN_SRCS} ${P4RUNTIME_GEN_HDRS}
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
-I ${P4RUNTIME_STD_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${Protobuf_PROTOC_EXECUTABLE}
-I${P4RUNTIME_STD_DIR} -I${CMAKE_CURRENT_SOURCE_DIR} -I${Protobuf_INCLUDE_DIR}
--cpp_out ${CMAKE_CURRENT_BINARY_DIR}
--python_out ${CMAKE_CURRENT_BINARY_DIR}
--experimental_allow_proto3_optional
Expand Down Expand Up @@ -96,7 +96,7 @@ add_library(controlplane-gen OBJECT ${P4RUNTIME_GEN_SRCS})
target_include_directories(controlplane-gen
SYSTEM BEFORE PUBLIC ${Protobuf_INCLUDE_DIR}
)
target_link_libraries (controlplane-gen PUBLIC ${PROTOBUF_LIBRARY})
target_link_libraries (controlplane-gen PUBLIC ${Protobuf_LIBRARY})
# Needed for the correct import of google/status.pb.cc
target_include_directories(
controlplane-gen PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
Expand Down

0 comments on commit 93dd245

Please sign in to comment.