Как я могу сгруппировать целевые зависимости в CMake? - PullRequest
1 голос
/ 14 февраля 2020

У меня довольно сложный проект на основе make, который я пытаюсь вместо этого использовать в современном CMake. В Makefile у меня есть несколько похожих общих библиотечных целей, которые имеют в основном идентичные флаги компиляции. Итак, это выглядело бы примерно так:

add_library(lib1 SHARED src1.cpp src2.cpp)
target_compile_options(lib1 PUBLIC -public-flag1 -public-flag2 -unique-flag3 PRIVATE -private-flag)

add_library(lib2 SHARED src3.cpp src4.cpp) 
target_compile_options(lib2 PUBLIC -public-flag -public-flag2 PRIVATE -private-flag)

Есть ли способ, которым я могу абстрагировать общие зависимости, чтобы мне не приходилось повторять их под каждой целью? Казалось бы, Интерфейсная библиотека была бы способом сделать это, что-то вроде:

add_library(common_options INTERFACE)
target_compile_options(common_options 
    PUBLIC -public-flag1 -public-flag2
    PRIVATE -private-flag
)
add_library(lib1 SHARED src1.cpp src2.cpp)
target_compile_options(lib1 PUBLIC -unique-flag3)
target_link_libraries(lib1 common_options)

add_library(lib2 SHARED src3.cpp src4.cpp) 
target_link_libraries(lib1 common_options)

, что, по моему мнению, было бы net выигрышем для удобства обслуживания. Тем не менее, CMake выдает ошибку при этом, жалуясь, что цель интерфейса может содержать только опции INTERFACE (я не могу добавить опции PRIVATE к ней). Есть ли другой способ сделать это, который позволил бы мне инкапсулировать флаги PUBLIC и PRIVATE, которые являются общими для целей?

1 Ответ

1 голос
/ 14 февраля 2020

Вы на правильном пути. Подумайте об этом:

add_library(public  INTERFACE)
add_library(private INTERFACE)
target_compile_options(public  INTERFACE -Werror)
target_compile_options(private INTERFACE -Wall)

target_link_libraries(lib1
    PUBLIC  # <-- public's flags will be applied to lib1 and any targets linking to lib1
        public
    PRIVATE # <-- private's flags will only be applied to lib1
        private
)

Короче говоря, вы забыли добавить области в своих вызовах к target_link_libraries.

Обновление :

Так что я думаю, что прямой ответ на мой вопрос заключается в том, что я не могу делать именно то, что хочу, а именно заключать в себе как частные, так и публичные c компиляции зависимостей опций в одну сущность. Вместо этого мне просто нужно сделать общедоступный и частный. Не так чисто, как я надеялся, но управляемо.

Не совсем, вам всегда нужно будет указывать PUBLIC и PRIVATE scope, но если вы хотите использовать target_compile_options вместо библиотек интерфейса для достижения этой цели, это также будет работать:

set(COMMON_FLAGS
    PUBLIC
        -Werror
        -ffast-math
    PRIVATE
        -Wall
)

target_compile_options(lib1 ${COMMON_FLAGS})
target_compile_options(lib2
    ${COMMON_FLAGS}
    PUBLIC # <-- you can still set scoped flags
        -fno-fast-math
)

Однако, на мой взгляд, использование библиотек интерфейса и просто дело с тем, что вы должны использовать PUBLIC и PRIVATE является более чистым и более легким в обслуживании в долгосрочной перспективе.

Кстати, если вы хотите сжать COMMON_FLAGS в одну строку: set(COMMON_FLAGS "PUBLIC;-Werror;-ffast-math;PRIVATE;-Wall")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...