2017-01-02 59 views
0

protobuf的文件,我已經看到了很多類似的問題和答案,但到現在爲止似乎不那麼明顯得到它的工作。我對CMake來說很新,直到現在,除了與協議緩衝區的集成以外,一切都很簡單。CMake的與子目錄

我有子目錄項目,其中每個子目錄都有自己的CMakeLists.txt

一個子目錄包含一個.proto文件。如果執行PROTOBUF_GENERATE_CPP宏,它將生成源文件和頭文件。該宏是從包含.proto文件的子目錄中的CMakeLists.txt調用的。

看來不過make文件不會被調用,因爲沒有源添加到目標。我不能源添加到目標,因爲不存在的文件,後一代,他們的存在,所以這會導致錯誤的CMake運行時。

設置文件屬性,以產生似乎也沒有幫助。一般來說,在構建過程開始之前,應該已經運行宏來生成源文件。

如何做到這一點,任何工作的例子嗎?

實施例:

./src/externals/protodef(從其它存儲庫中,只包含.proto文件)
./src/generated(假定用於通過protoc生成的C和頭文件)

CMakeLists-1(項目根)

cmake_minimum_required (VERSION 2.6) 
PROJECT (prototest) 

ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src/externals/protodef") 
ADD_SUBDIRECTORY("${PROJECT_SOURCE_DIR}/src") 

SET_SOURCE_FILES_PROPERTIES(${PROTO_SOURCES} ${PROTO_HEADERS} PROPERTIES GENERATED TRUE) 

ADD_EXECUTABLE(prototest ${PROTO_SOURCES} ${SOURCE}) 
TARGET_LINK_LIBRARIES(prototest ${EXTERNAL_LIBS}) 

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 

CMakeLists-2(SRC)

SET(SOURCE ${SOURCE} 
    ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp 

    PARENT_SCOPE 
) 

CMakeLists-3(SRC /外部對象/ protodef)

SET(PROTOBUF_PATH "D:/protobuf-3.0.0/") 
SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${PROTOBUF_PATH}") 

# Changing PROTO_SRCS and PROTO_HDRS does not work for setting the location 
# of the generated files. 
# Those variable are ignored by CMake for compiling the proto files. 
# Using a dedicated CMakeLists.txt and settng CURRENT_BINARY dir is a 
# workaround to get them where we want. 
SET(GENERATED_DIR ${PROJECT_SOURCE_DIR}/src/generated) 
SET(CMAKE_CURRENT_BINARY_DIR ${GENERATED_DIR}) 


INCLUDE(FindProtobuf) 
FIND_PACKAGE(Protobuf REQUIRED) 

PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS${CMAKE_CURRENT_SOURCE_DIR}/test1.proto) 

SET(EXTERNAL_LIBS ${PROTOBUF_PATH}/lib/libprotobuf.a PARENT_SCOPE) 

# Propagate sources to the parant project 
SET(PROTO_SOURCES ${PROTO_SRCS} 
PARENT_SCOPE 
) 

SET(PROTO_HEADERS ${PROTO_HDRS} 
PARENT_SCOPE 
) 
+0

請發表[MCVE] –

+0

你必須標記與生成的屬性生成的.h和.cpp文件,使CMake的人都知道,當談到時間,使他們就會存在。 –

+0

@Richard我試着設置GENERATED屬性。看起來它唯一要做的就是將文件名「要生成」填入傳遞給宏的變量中。但在這種情況下,文件仍然不存在,並將變量添加到項目源文件,然後導致cmake錯誤,因爲它包含一個不存在的文件的名稱。 – Waldorf

回答

0

首先生成protobuf的文件,然後將它們添加到一個目標的CMake。

CMakeLists(SRC):

# Generate h/cpp proto files (./src/externals/protodef) into ./src/generated folder 
PROTOBUF_GENERATE_CPP(...) 

# Process subdir 
ADD_SUBDIRECTORY(generated) 

似乎PROTOBUF_GENERATE_CPP只能在同一個子目錄中。一個可能的解決方法是調用protoc直接代替:

FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/externals/protodef PROTOMODEL_PATH) 
FILE(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/src/generated PROTOBINDING_PATH) 

FILE(GLOB DATAMODEL_PROTOS "${CMAKE_CURRENT_SOURCE_DIR}/externals/protodef/*.proto") 

FOREACH(proto ${DATAMODEL_PROTOS}) 
    FILE(TO_NATIVE_PATH ${proto} proto_native) 
    EXECUTE_PROCESS(COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --proto_path=${PROTOMODEL_PATH} --cpp_out=${PROTOBINDING_PATH} ${proto_native} 
    RESULT_VARIABLE rv) 
    # Optional, but that can show the user if something have gone wrong with the proto generation 
    IF(${rv}) 
     MESSAGE("Generation of data model returned ${rv} for proto ${proto_native}") 
    ENDIF() 
ENDFOREACH(proto) 

CMakeLists(SRC /生成):

## List generated sources files 
FILE(GLOB HDRS "*.h") 
FILE(GLOB SRCS "*.cc") 

ADD_LIBRARY(protoBinding ${HDRS} ${SRCS}) 
# ${PROTOBUF_LIBRARIES} should be defined by FIND_PACKAGE(Protobuf REQUIRED) 
TARGET_LINK_LIBRARIES(protoBinding ${PROTOBUF_LIBRARIES}) 

這樣的CMake將首先產生頁眉/源文件,並且僅然後添加生成的文件到CMake目標。

然後可以使用protoBinding目標生成的文件鏈接到其他目標(例如,在src的的CMakeLists.txt年底):

ADD_LIBRARY(myModel ${myFiles}) 
TARGET_LINK_LIBRARIES(myModel protoBinding) 
+0

我使用了第二個選項,它提供了更多的控制權。它像一個魅力。 在我的情況下,PROTOBUF_LIBRARIES指向libprotobuf.dll.a 我想按照Google的建議靜態鏈接libprotobuf。目前我手動設置庫,可能有一個更清晰的方法。 – Waldorf