include_guard(GLOBAL) function(myx_target_setup TARGET_NAME) set(options) set(oneValueArgs PCH) set(multiValueArgs PACKAGES COMPILE_DEFINITIONS INCLUDE_DIRECTORIES LINK_LIBRARIES CPP PUBLIC_HEADERS PRIVATE_HEADERS) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT TARGET ${TARGET_NAME}) myx_message_fatal_error("Target ${TARGET_NAME} does not exists.") endif() get_target_property(target_type ${TARGET_NAME} TYPE) if(${target_type} STREQUAL "INTERFACE_LIBRARY") myx_message_fatal_error("This function will not work for interface targets.") endif() foreach(iter ${ARG_PACKAGES}) target_include_directories(${TARGET_NAME} PRIVATE ${${iter}_INCLUDE_DIRS}) target_compile_definitions(${TARGET_NAME} PRIVATE ${${iter}_COMPILE_DEFINITIONS}) endforeach() if(ARG_CPP) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY CPP_FILES ${ARG_CPP}) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_CPP}) endif() if(ARG_PUBLIC_HEADERS) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY PUBLIC_HEADER_FILES "${ARG_PUBLIC_HEADERS}") set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_PUBLIC_HEADERS}) endif() if(ARG_PRIVATE_HEADERS) set_property(TARGET ${TARGET_NAME} APPEND PROPERTY PRIVATE_HEADER_FILES "${ARG_PRIVATE_HEADERS}") set_property(TARGET ${TARGET_NAME} APPEND PROPERTY TR_FILES ${ARG_PRIVATE_HEADERS}) endif() if(ARG_PCH) if((${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.16) AND (PROJECT_IS_TOP_LEVEL OR MYX_USE_LOCAL_DIRECTORIES)) target_precompile_headers(${TARGET_NAME} PRIVATE ${ARG_PCH}) else() target_compile_options(${TARGET_NAME} PRIVATE -include ${ARG_PCH}) endif() set_property(TARGET ${TARGET_NAME} APPEND PROPERTY PRIVATE_HEADER_FILES "${ARG_PCH}") endif() target_include_directories(${PROJECT_NAME} PRIVATE $) if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/src") target_include_directories(${PROJECT_NAME} PRIVATE $) endif() if(target_type STREQUAL "EXECUTABLE") if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/include") target_include_directories(${PROJECT_NAME} PRIVATE $) endif() if(IS_DIRECTORY "${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}") target_include_directories(${PROJECT_NAME} PRIVATE $) endif() set_target_properties(${TARGET_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} ) if(CMAKE_CXX_COMPILE_OPTIONS_PIE) target_compile_options(${TARGET_NAME} PUBLIC ${CMAKE_CXX_COMPILE_OPTIONS_PIE}) endif() install(TARGETS ${TARGET_NAME} COMPONENT MAIN RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() target_sources(${TARGET_NAME} PRIVATE ${ARG_CPP} ${ARG_PCH} ${ARG_PRIVATE_HEADERS}) target_compile_definitions(${TARGET_NAME} PRIVATE ${ARG_COMPILE_DEFINITIONS}) target_include_directories(${TARGET_NAME} PRIVATE ${ARG_INCLUDE_DIRECTORIES}) # CMake до версии 3.12 не умеет извлекать из целей типа `OBJECT_LIBRARY` # информацию о заголовочных файлах. Это обход. if(${CMAKE_VERSION} VERSION_GREATER "3.11.99") target_link_libraries(${TARGET_NAME} PRIVATE ${ARG_LINK_LIBRARIES}) else() if((NOT ${target_type} STREQUAL "OBJECT_LIBRARY") AND (NOT ${target_type} STREQUAL "EXECUTABLE")) target_link_libraries(${TARGET_NAME} PRIVATE ${ARG_LINK_LIBRARIES}) else() foreach(__link_library ${ARG_LINK_LIBRARIES}) if(TARGET ${__link_library}) get_target_property(__lib_type ${__link_library} TYPE) if(__lib_type) get_target_property(__include_dirs ${__link_library} INTERFACE_INCLUDE_DIRECTORIES) if(__include_dirs) target_include_directories(${TARGET_NAME} PUBLIC ${__include_dirs}) endif() if(${target_type} STREQUAL "EXECUTABLE") if(${__lib_type} STREQUAL "OBJECT_LIBRARY") if(TARGET ${__link_library}_static) target_link_libraries(${TARGET_NAME} PRIVATE ${__link_library}_static) else() target_link_libraries(${TARGET_NAME} PRIVATE ${__link_library}_shared) endif() else() target_link_libraries(${TARGET_NAME} PRIVATE ${__link_library}) endif() endif() endif() else() if((${CMAKE_VERSION} VERSION_GREATER "3.7.99") OR (NOT target_type STREQUAL "OBJECT_LIBRARY")) target_link_libraries(${TARGET_NAME} PRIVATE ${__link_library}) endif() endif() endforeach() endif() endif() # Установка публичных заголовочных файлов if(PROJECT_IS_TOP_LEVEL AND ARG_PUBLIC_HEADERS) myx_install_relative(${PROJECT_SOURCE_DIR} FILES ${ARG_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT DEV ) endif() endfunction()