cmake / target_** 中的 PUBLIC,PRIVATE,INTERFACE
一、指令說明
target_include_directories():指定目標包含的頭文件路徑。官方文檔
target_link_libraries():指定目標鏈接的庫。官方文檔
target_compile_options():指定目標的編譯選項。官方文檔
目標 由 add_library() 或 add_executable() 生成。
這三個指令類似,這里以 target_include_directories() 為例進行講解。
二、指令講解
測試工程目錄結構:
cmake-test/ 工程主目錄,main.c 調用 libhello-world.so ├── CMakeLists.txt ├── hello-world 生成 libhello-world.so,調用 libhello.so 和 libworld.so │ ├── CMakeLists.txt │ ├── hello 生成 libhello.so │ │ ├── CMakeLists.txt │ │ ├── hello.c │ │ └── hello.h libhello.so 對外的頭文件 │ ├── hello_world.c │ ├── hello_world.h libhello-world.so 對外的頭文件 │ └── world 生成 libworld.so │ ├── CMakeLists.txt │ ├── world.c │ └── world.h libworld.so 對外的頭文件 └── main.c調用關系:
├────libhello.so 可執行文件────libhello-world.so├────libworld.so關鍵字用法說明:
PRIVATE:私有的。生成 libhello-world.so 時,只在 hello_world.c 中包含了 hello.h,libhello-world.so 對外的頭文件 -- hello_world.h 中不包含 hello.h。而且 main.c 不會調用 hello.c 中的函數,或者說 main.c 不知道 hello.c 的存在,那么在 hello-world / CMakeLists.txt 中應該寫入:
target_link_libraries(hello-world PRIVATE hello) target_include_directories(hello-world PRIVATE hello)INTERFACE:接口。生成 libhello-world.so 時,只在 libhello-world.so 對外的頭文件——hello_world.h 中包含 了 hello.h, hello_world.c 中不包含 hello.h,即 libhello-world.so 不使用 libhello.so 提供的功能,只使用 hello.h 中的某些信息,比如結構體。但是 main.c 需要使用 libhello.so 中的功能。那么在 hello-world/CMakeLists.txt 中應該寫入:
target_link_libraries(hello-world INTERFACE hello) target_include_directories(hello-world INTERFACE hello)PUBLIC:公開的。PUBLIC = PRIVATE + INTERFACE。生成 libhello-world.so 時,在 hello_world.c 和 hello_world.h 中都包含了 hello.h。并且 main.c 中也需要使用 libhello.so 提供的功能。那么在 hello-world/CMakeLists.txt 中應該寫入:
target_link_libraries(hello-world PUBLIC hello) target_include_directories(hello-world PUBLIC hello)實際上,這三個關鍵字指定的是目標文件依賴項的使用范圍(scope)或者一種傳遞
(propagate)。官方說明
可執行文件依賴 libhello-world.so, libhello-world.so 依賴 libhello.so 和 libworld.so。
三、include_directories(dir)
target_include_directories() 的功能完全可以使用 include_directories() 實現。但是我還是建議使用 target_include_directories()。為什么?保持清晰!
include_directories(header-dir) 是一個全局包含,向下傳遞。什么意思呢?就是說如果某個目錄的 CMakeLists.txt 中使用了該指令,其下所有的子目錄默認也包含了 header-dir 目錄。
上述例子中,如果在頂層的 cmake-test / CMakeLists.txt 中加入:
include_directories(hello-world) include_directories(hello-world/hello) include_directories(hello-world/world)那么整個工程的源文件在編譯時都會增加:
-I hello-world -I hello-world/hello -I hello-world/world ...各級子目錄中無需使用 target_include_directories() 或者 include_directories()了。如果此時查看詳細的編譯過程(make VERBOSE=1)就會發現編譯過程是一大坨,很不舒服。
當然了,在最終子目錄的 CMakeLists.txt 文件中,使用 include_directories() 和 target_include_directories() 的效果是相同的。
4. 目錄劃分
每一個目錄都是一個模塊,目錄內部應將對外和對內的頭文件進行區分,由模塊的調用者決定模塊是否被傳遞(PRIVATE,INTERFACE,PUBLIC)。
轉載:cmake:target_** 中的 PUBLIC,PRIVATE,INTERFACE - 知乎
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的cmake / target_** 中的 PUBLIC,PRIVATE,INTERFACE的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OS / Linux / 制作 deb
- 下一篇: cmake / add_compile_