How to substitute the extension for a cmake list of filenames

Viewed 2795

I am trying to build a c++ library from some protobuf definitions using cmake. I added a custom command to compile the proto to c++, but I have some issues with the output part. I need to specify which are the expected output files after protoc does its job. For this I would like to replace in my PROTO_SOURCEfile glob, the proto extension with .pb.cc and .pb.h

I basically need something like this, but for cmake.

I am building this command manually because I don't have protobuf cmake support available.

project(messages)

set(PROTO_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proto_definitions")
file(GLOB PROTO_FILES "${PROTO_PATH}/*.proto")
#set(PROTO_SOURCES ???) # This needs to contain '*.pb.cc' and '*.pb.h'

add_custom_command(COMMAND protoc --cpp_out=${CMAKE_CURRENT_SOURCE_DIR}/compiled_proto ${PROTO_FILES}
               WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
               DEPENDS ${PROTO_FILES}
               OUTPUT ${PROTO_SOURCES})

add_library(${PROJECT_NAME} STATIC ${PROTO_SOURCES})
2 Answers

Use string(REGEX REPLACE) function:

# Replace .proto -> .pb.cc
string(REGEX REPLACE "[.]proto$" ".pb.cc" OUTPUT_SOURCES ${PROTO_FILES})
# Replace .proto -> .pb.h
string(REGEX REPLACE "[.]proto$" ".pb.h" OUTPUT_HEADERS ${PROTO_FILES})

add_custom_command(COMMAND protoc <...>
   OUTPUT ${OUTPUT_SOURCES} ${OUTPUT_HEADERS})

The accepted answer didn't work for me, as the first few elements in the list weren't properly substituted.

So I loop over the list, replace them one by one, and append each one to a list:

foreach (CXX_SRC ${LIST_OF_CXX})
    string(REGEX REPLACE "[.]cpp$" ".o" OBJ ${CXX_SRC})
    set(OBJ_FILES ${OBJ_FILES} ${OBJ})
endforeach ()
message(STATUS "Object files compiled from *.cpp: ${OBJ_FILES}")
Related