+ # Generate library target that can be referenced elsewhere. Force static, because
+ # we can't easily export symbols from the generated sources.
+ quassel_add_module(Resource::${_name} STATIC)
+ target_sources(${TARGET} PRIVATE ${qrc_srcpath})
+ set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF AUTOUIC OFF AUTORCC OFF)
+
+ # Set variable for referencing the target from outside
+ set(RESOURCE_TARGET ${TARGET} PARENT_SCOPE)
+endfunction()
+
+###################################################################################################
+# Adds a unit test case
+#
+# quassel_add_test(TestName
+# [LIBRARIES lib1 lib2...]
+# )
+#
+# The test name is given in CamelCase as first and mandatory parameter. The corresponding source file
+# is expected the lower-cased test name plus the .cpp extension.
+# The test case is automatically linked against Qt5::Test, GMock, Quassel::Common and
+# Quassel::Test::Main, which contains the main function. This main function also instantiates a
+# QCoreApplication, so the event loop can be used in test cases.
+#
+# Additional libraries can be given using the LIBRARIES argument.
+#
+# Test cases should include testglobal.h, which transitively includes the GTest/GMock headers and
+# exports the main function.
+#
+# The compiled test case binary is located in the unit/ directory in the build directory.
+#
+function(quassel_add_test _target)
+ set(options )
+ set(oneValueArgs )
+ set(multiValueArgs LIBRARIES)
+ cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ string(TOLOWER ${_target} lower_target)
+ set(srcfile ${lower_target}.cpp)
+
+ list(APPEND ARG_LIBRARIES
+ Qt5::Test
+ Quassel::Common
+ Quassel::Test::Global
+ Quassel::Test::Main
+ )
+
+ if (WIN32)
+ # On Windows, tests need to be built in the same directory that contains the libraries
+ set(output_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+ else()
+ # On other platforms, separate the test cases out
+ set(output_dir "${CMAKE_BINARY_DIR}/unit")
+ endif()
+
+ add_executable(${_target} ${srcfile})
+ set_target_properties(${_target} PROPERTIES
+ OUTPUT_NAME ${_target}
+ RUNTIME_OUTPUT_DIRECTORY "${output_dir}"
+ )
+ target_link_libraries(${_target} PUBLIC ${ARG_LIBRARIES})
+
+ add_test(
+ NAME ${_target}
+ COMMAND $<TARGET_FILE:${_target}>
+ WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+ )
+endfunction()
+
+###################################################################################################
+# target_link_if_exists(Target
+# [PUBLIC dep1 dep2...]
+# [PRIVATE dep3 dep4...]
+# )
+#
+# Convenience function to add dependencies to a target only if they exist. This is useful when
+# handling targets that are conditionally created, e.g. resource libraries depending on -DEMBED_DATA.
+#
+# NOTE: In order to link a given target, it must already have been created, i.e its subdirectory
+# must already have been added. This is also true for globally visible ALIAS targets that
+# can otherwise be linked to regardless of creation order; "if (TARGET...)" does not
+# support handling this case correctly.
+#
+function(target_link_if_exists _target)
+ set(options )
+ set(oneValueArgs )
+ set(multiValueArgs PUBLIC PRIVATE)
+ cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if (ARG_PUBLIC)
+ foreach(dep ${ARG_PUBLIC})
+ if (TARGET ${dep})
+ target_link_libraries(${_target} PUBLIC ${dep})
+ endif()
+ endforeach()