337 lines
11 KiB
CMake
337 lines
11 KiB
CMake
include_guard(DIRECTORY)
|
|
|
|
#[[
|
|
Add qt translation target.
|
|
|
|
qm_add_translation(<target>
|
|
[LOCALES locales]
|
|
[PREFIX prefix]
|
|
[SOURCES files... | DIRECTORIES dirs... | TARGETS targets... | TS_FILES files...]
|
|
[TS_DIR dir]
|
|
[QM_DIR dir]
|
|
[TS_OPTIONS options...]
|
|
[QM_OPTIONS options...]
|
|
[TS_DEPENDS targets...]
|
|
[QM_DEPENDS targets...]
|
|
)
|
|
|
|
Arguments:
|
|
LOCALES: language names, e.g. zh_CN en_US, must specify if SOURCES or TARGETS is specified
|
|
PREFIX: translation file prefix, default to target name
|
|
|
|
SOURCES: source files
|
|
DIRECTORIES: source directories
|
|
TARGETS: target names, the source files of which will be collected
|
|
TS_FILES: ts file names, add the specified ts file
|
|
|
|
TS_DIR: ts files destination, default to `CMAKE_CURRENT_SOURCE_DIR`
|
|
QM_DIR: qm files destination, default to `CMAKE_CURRENT_BINARY_DIR`
|
|
|
|
TS_DEPENDS: add lupdate task as a dependency to the given targets
|
|
QM_DEPENDS: add lrelease task as a dependency to the given targets
|
|
|
|
]] #
|
|
function(qm_add_translation _target)
|
|
set(options)
|
|
set(oneValueArgs PREFIX TS_DIR QM_DIR)
|
|
set(multiValueArgs LOCALES SOURCES DIRECTORIES TARGETS TS_FILES TS_OPTIONS QM_OPTIONS TS_DEPENDS QM_DEPENDS)
|
|
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
# Get linguist tools
|
|
if(NOT TARGET Qt${QT_VERSION_MAJOR}::lupdate OR NOT TARGET Qt${QT_VERSION_MAJOR}::lrelease)
|
|
message(FATAL_ERROR "qm_add_translation: linguist tools not defined. Add find_package(Qt5 COMPONENTS LinguistTools) to CMake to enable.")
|
|
endif()
|
|
|
|
set(_src_files)
|
|
set(_include_dirs)
|
|
|
|
# Collect source files
|
|
if(FUNC_SOURCES)
|
|
list(APPEND _src_files ${FUNC_SOURCES})
|
|
endif()
|
|
|
|
# Collect source directories
|
|
if(FUNC_DIRECTORIES)
|
|
foreach(_item IN LISTS FUNC_DIRECTORIES)
|
|
file(GLOB _tmp
|
|
${_item}/*.h ${_item}/*.hpp
|
|
${_item}/*.hh ${_item}/*.hxx
|
|
${_item}/*.cpp ${_item}/*.cxx
|
|
${_item}/*.c ${_item}/*.cc
|
|
${_item}/*.m ${_item}/*.mm
|
|
)
|
|
list(APPEND _src_files ${_tmp})
|
|
endforeach()
|
|
endif()
|
|
|
|
# Collect source files
|
|
if(FUNC_TARGETS)
|
|
foreach(_item IN LISTS FUNC_TARGETS)
|
|
get_target_property(_type ${_item} TYPE)
|
|
|
|
if((_type STREQUAL "UTILITY") OR (_type STREQUAL "INTERFACE_LIBRARY"))
|
|
continue()
|
|
endif()
|
|
|
|
set(_tmp_files)
|
|
get_target_property(_tmp_files ${_item} SOURCES)
|
|
list(FILTER _tmp_files INCLUDE REGEX ".+\\.(h|hh|hpp|hxx|c|cc|cpp|cxx|m|mm)$")
|
|
list(FILTER _tmp_files EXCLUDE REGEX "^(qasc|moc)_.+")
|
|
|
|
# Need to convert to absolute path
|
|
get_target_property(_target_dir ${_item} SOURCE_DIR)
|
|
|
|
foreach(_file IN LISTS _tmp_files)
|
|
get_filename_component(_abs_file ${_file} ABSOLUTE BASE_DIR ${_target_dir})
|
|
list(APPEND _src_files ${_abs_file})
|
|
endforeach()
|
|
|
|
unset(_tmp_files)
|
|
|
|
get_target_property(_tmp_dirs ${_item} INCLUDE_DIRECTORIES)
|
|
list(APPEND _include_dirs ${_tmp_dirs})
|
|
endforeach()
|
|
endif()
|
|
|
|
if(_src_files)
|
|
if(NOT FUNC_LOCALES)
|
|
message(FATAL_ERROR "qm_add_translation: source files collected but LOCALES not specified!")
|
|
endif()
|
|
elseif(NOT FUNC_TS_FILES)
|
|
message(FATAL_ERROR "qm_add_translation: no source files or ts files collected!")
|
|
endif()
|
|
|
|
add_custom_target(${_target})
|
|
|
|
set(_qm_depends)
|
|
|
|
if(FUNC_TS_OPTIONS)
|
|
set(_ts_options ${FUNC_TS_OPTIONS})
|
|
endif()
|
|
|
|
if(FUNC_QM_OPTIONS)
|
|
set(_qm_options ${FUNC_QM_OPTIONS})
|
|
endif()
|
|
|
|
if(_src_files)
|
|
if(FUNC_PREFIX)
|
|
set(_prefix ${FUNC_PREFIX})
|
|
else()
|
|
set(_prefix ${_target})
|
|
endif()
|
|
|
|
if(FUNC_TS_DIR)
|
|
set(_ts_dir ${FUNC_TS_DIR})
|
|
else()
|
|
set(_ts_dir ${CMAKE_CURRENT_SOURCE_DIR})
|
|
endif()
|
|
|
|
set(_ts_files)
|
|
|
|
foreach(_loc IN LISTS FUNC_LOCALES)
|
|
list(APPEND _ts_files ${_ts_dir}/${_prefix}_${_loc}.ts)
|
|
endforeach()
|
|
|
|
# Include options
|
|
set(_include_options)
|
|
|
|
foreach(_inc IN LISTS _include_dirs)
|
|
list(APPEND _include_options "-I${_inc}")
|
|
endforeach()
|
|
|
|
# May be an lupdate bug, so we skip passing include directories
|
|
# list(APPEND _ts_options ${_include_options})
|
|
if(_ts_options)
|
|
list(PREPEND _ts_options OPTIONS)
|
|
endif()
|
|
|
|
_qm_add_lupdate_target(${_target}_lupdate
|
|
INPUT ${_src_files}
|
|
OUTPUT ${_ts_files}
|
|
${_ts_options}
|
|
CREATE_ONCE
|
|
)
|
|
|
|
# Add update dependencies
|
|
# add_dependencies(${_target} ${_target}_lupdate)
|
|
foreach(_item IN LISTS FUNC_TS_DEPENDS)
|
|
add_dependencies(${_item} ${_target}_lupdate)
|
|
endforeach()
|
|
|
|
# list(APPEND _qm_depends DEPENDS ${_target}_lupdate)
|
|
else()
|
|
if(FUNC_PREFIX)
|
|
message(WARNING "qm_add_translation: no source files collected, PREFIX ignored")
|
|
endif()
|
|
|
|
if(FUNC_TS_DIR)
|
|
message(WARNING "qm_add_translation: no source files collected, TS_DIR ignored")
|
|
endif()
|
|
|
|
if(FUNC_TS_DEPENDS)
|
|
message(WARNING "qm_add_translation: no source files collected, TS_DEPENDS ignored")
|
|
endif()
|
|
endif()
|
|
|
|
if(FUNC_QM_DIR)
|
|
set(_qm_dir ${FUNC_QM_DIR})
|
|
else()
|
|
set(_qm_dir ${CMAKE_CURRENT_BINARY_DIR})
|
|
endif()
|
|
|
|
set(_qm_target)
|
|
|
|
if(_qm_options)
|
|
list(PREPEND _qm_options OPTIONS)
|
|
endif()
|
|
|
|
_qm_add_lrelease_target(${_target}_lrelease
|
|
INPUT ${_ts_files} ${FUNC_TS_FILES}
|
|
DESTINATION ${_qm_dir}
|
|
${_qm_options}
|
|
${_qm_depends}
|
|
)
|
|
|
|
add_dependencies(${_target} ${_target}_lrelease)
|
|
|
|
# Add release dependencies
|
|
if(FUNC_TARGETS)
|
|
foreach(_item IN LISTS FUNC_TARGETS)
|
|
add_dependencies(${_item} ${_target}_lrelease)
|
|
endforeach()
|
|
endif()
|
|
|
|
foreach(_item IN LISTS FUNC_QM_DEPENDS)
|
|
add_dependencies(${_item} ${_target}_lrelease)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# ----------------------------------
|
|
# Private functions
|
|
# ----------------------------------
|
|
# Input: cxx source files
|
|
# Output: target ts files
|
|
function(_qm_add_lupdate_target _target)
|
|
set(options CREATE_ONCE)
|
|
set(oneValueArgs)
|
|
set(multiValueArgs INPUT OUTPUT OPTIONS DEPENDS)
|
|
|
|
cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
set(_lupdate_deps ${_LUPDATE_DEPENDS})
|
|
|
|
set(_my_sources ${_LUPDATE_INPUT})
|
|
set(_my_tsfiles ${_LUPDATE_OUTPUT})
|
|
|
|
add_custom_target(${_target} DEPENDS ${_lupdate_deps})
|
|
get_target_property(_lupdate_exe Qt${QT_VERSION_MAJOR}::lupdate IMPORTED_LOCATION)
|
|
|
|
foreach(_ts_file IN LISTS _my_tsfiles)
|
|
# make a list file to call lupdate on, so we don't make our commands too
|
|
# long for some systems
|
|
get_filename_component(_ts_name ${_ts_file} NAME)
|
|
set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file")
|
|
set(_lst_file_srcs)
|
|
|
|
foreach(_lst_file_src IN LISTS _my_sources)
|
|
set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}")
|
|
endforeach()
|
|
|
|
get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES)
|
|
|
|
foreach(_pro_include IN LISTS _inc_DIRS)
|
|
get_filename_component(_abs_include "${_pro_include}" ABSOLUTE)
|
|
set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}")
|
|
endforeach()
|
|
|
|
file(WRITE ${_ts_lst_file} "${_lst_file_srcs}")
|
|
|
|
get_filename_component(_ts_abs ${_ts_file} ABSOLUTE)
|
|
|
|
if(_LUPDATE_CREATE_ONCE AND NOT EXISTS ${_ts_abs})
|
|
set(_options_filtered)
|
|
|
|
foreach(_opt IN LISTS _LUPDATE_OPTIONS)
|
|
qm_has_genex(${_opt} _has_genex)
|
|
|
|
if(_has_genex)
|
|
continue()
|
|
endif()
|
|
|
|
list(APPEND _options_filtered ${_opt})
|
|
endforeach()
|
|
|
|
message(STATUS "Linguist update: Generate ${_ts_name}")
|
|
get_filename_component(_abs_file ${_ts_file} ABSOLUTE)
|
|
get_filename_component(_dir ${_abs_file} DIRECTORY)
|
|
make_directory(${_dir})
|
|
execute_process(
|
|
COMMAND ${_lupdate_exe} ${_options_filtered} "@${_ts_lst_file}" -ts ${_ts_file}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
OUTPUT_QUIET
|
|
COMMAND_ERROR_IS_FATAL ANY
|
|
)
|
|
endif()
|
|
|
|
add_custom_command(
|
|
TARGET ${_target}
|
|
COMMAND ${_lupdate_exe}
|
|
ARGS ${_LUPDATE_OPTIONS} "@${_ts_lst_file}" -ts ${_ts_file}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
DEPENDS ${_my_sources}
|
|
BYPRODUCTS ${_ts_lst_file}
|
|
VERBATIM
|
|
)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# Input: ts files
|
|
# Output: list to append qm files
|
|
function(_qm_add_lrelease_target _target)
|
|
set(options)
|
|
set(oneValueArgs DESTINATION OUTPUT)
|
|
set(multiValueArgs INPUT OPTIONS DEPENDS)
|
|
|
|
cmake_parse_arguments(_LRELEASE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
set(_lrelease_files ${_LRELEASE_INPUT})
|
|
set(_lrelease_deps ${_LRELEASE_DEPENDS})
|
|
|
|
get_target_property(_lrelease_exe Qt${QT_VERSION_MAJOR}::lrelease IMPORTED_LOCATION)
|
|
|
|
set(_qm_files)
|
|
|
|
foreach(_file IN LISTS _lrelease_files)
|
|
get_filename_component(_abs_FILE ${_file} ABSOLUTE)
|
|
get_filename_component(_qm_file ${_file} NAME)
|
|
|
|
# everything before the last dot has to be considered the file name (including other dots)
|
|
string(REGEX REPLACE "\\.[^.]*$" "" FILE_NAME ${_qm_file})
|
|
get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION)
|
|
|
|
if(output_location)
|
|
set(_out_dir ${output_location})
|
|
elseif(_LRELEASE_DESTINATION)
|
|
set(_out_dir ${_LRELEASE_DESTINATION})
|
|
else()
|
|
set(_out_dir ${CMAKE_CURRENT_BINARY_DIR})
|
|
endif()
|
|
|
|
set(_qm_file "${_out_dir}/${FILE_NAME}.qm")
|
|
|
|
add_custom_command(
|
|
OUTPUT ${_qm_file}
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${_out_dir}
|
|
COMMAND ${_lrelease_exe} ARGS ${_LRELEASE_OPTIONS} ${_abs_FILE} -qm ${_qm_file}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
DEPENDS ${_lrelease_files}
|
|
VERBATIM
|
|
)
|
|
|
|
list(APPEND _qm_files ${_qm_file})
|
|
endforeach()
|
|
|
|
add_custom_target(${_target} ALL DEPENDS ${_lrelease_deps} ${_qm_files})
|
|
|
|
if(_LRELEASE_OUTPUT)
|
|
set(${_LRELEASE_OUTPUT} ${_qm_files} PARENT_SCOPE)
|
|
endif()
|
|
endfunction() |