From 5eafe9475cca1269615e29d37eb434378715d7c7 Mon Sep 17 00:00:00 2001 From: Eduard Bloch Date: Sat, 28 Sep 2024 10:37:34 +0200 Subject: [PATCH] Fix and streamline conversion flow - fix bad vim modeline, align with parent folder - simplified flow, making it straight with control options rather than depending obscure targets - document the flow - explicit developer options to control the behavior - drop deprecated option in POT creation (xgettext warning) --- po/CMakeLists.txt | 213 +++++++++++++++++++++++++++++----------------- 1 file changed, 135 insertions(+), 78 deletions(-) diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt index cb856ae17..1b6d77fa4 100644 --- a/po/CMakeLists.txt +++ b/po/CMakeLists.txt @@ -1,11 +1,43 @@ cmake_minimum_required(VERSION 3.5) -PROJECT(ICEWM CXX) - -# yes, FindGettext.cmake exists but it's not really handy :-( -# XXX: document -DEXTRA_MSGMERGE=--verbose -DEXTRA_MSGFMT=--verbose +project(ICEWM CXX) + +# +# Custom PO file processing (POT extraction/update, PO merging, MO building). +# +# Callable custom targets (part of ALL target): +# +# The default rule set updates pot, *.po, and compiles *.(g)mo from the updated +# versions. Also some CACHED options: +# - with PO_REPLACE options, the updated files are sync'ed back to source code +# folder in the build phase. +# - with PO_REPLACE_ONCE the original PO/POT files are replaced once and then +# not again (cached) +# - with SKIP_TRANSLATIONS, the whole PO processing is turned off and MO files +# are NOT installed. This might be handy in the development process. +# +# when gettext tools are missing, no processing is performed. +# + +option(SKIP_TRANSLATIONS "[DEV] Don't perform PO/MO file creation or installation" off) +option(PO_VERBOSE "[DEV] Extra verbosity in gettext processing (extends EXTRA_MSGMERGE and EXTRA_MSGMERGE)" off) +option(PO_REPLACE "[DEV] Install updated POT/PO files in source folder" off) +option(PO_REPLACE_ONCE "[DEV] Like PO_REPLACE but turns itself off after one run" off) + +if(SKIP_TRANSLATIONS) + message(STATUS "Language file processing disabled by SKIP_TRANSLATIONS option") + return() +endif() -SET(EXTRA_MSGMERGE "--quiet") +if(PO_VERBOSE) + list(APPEND EXTRA_MSGMERGE --verbose) + list(APPEND EXTRA_MSGFMT --verbose) +else() + list(APPEND EXTRA_MSGMERGE --quiet) +endif() +# +# NOTE: FindGettext.cmake exists but it's not really handy :-( +# find_program(gettext gettext) find_program(xgettext xgettext) find_program(msgmerge msgmerge) @@ -14,81 +46,106 @@ find_program(msgfmt msgfmt) set(COPYRIGHT_HOLDER "Marko Macek ") set(BUG_ADDRESS "https://github.com/bbidulock/icewm/issues") -if(gettext AND xgettext AND msgmerge AND msgfmt) - file (STRINGS "POTFILES.in" SRCS) - # grrr, for make dependency the path needs to match the perspective from the po/ directory. - # FIXME, how to simplify? Use abs.path for now - foreach(_src ${SRCS}) - LIST(APPEND SRCSABSOLUTE "${CMAKE_SOURCE_DIR}/${_src}") - endforeach() - FILE(GLOB POS "${CMAKE_CURRENT_SOURCE_DIR}/*.po") - foreach(_src ${POS}) - get_filename_component(_src "${_src}" NAME_WE) - LIST(APPEND LANGUAGES ${_src}) - endforeach() - - SET(XGETTEXT_CMD xgettext --from-code=UTF-8 -language=CXX --add-comments=TRANSLATORS: --keyword=_ --keyword=N_ -s --package-name=${PACKAGE} --copyright-holder="${COPYRIGHT_HOLDER}" --package-version="${VERSION}" --msgid-bugs-address="${BUG_ADDRESS}" ) - SET(_potFile "${CMAKE_CURRENT_SOURCE_DIR}/${PACKAGE}.pot") - - # XXX: it "escapes" spaces in arguments no matter how they are quoted. Find a workaround! - ADD_CUSTOM_COMMAND(OUTPUT stamp-potfile - COMMAND ${XGETTEXT_CMD} -o "${_potFile}" ${SRCS} - DEPENDS ${SRCSABSOLUTE} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMENT "Extracting translatable messages to ${_potFile} -- may require config restart!") - ADD_CUSTOM_TARGET(update_pot DEPENDS stamp-potfile) - message(VERBOSE "Adding update_pot target to update ${_potFile}") - - if(EXISTS ${_potFile}) - - if(SKIP_TRANSLATIONS) - message(VERBOSE "NOTE: SKIP_TRANSLATIONS is set, building i18n files is not part of the default build!") - ADD_CUSTOM_TARGET(translations) - else() - ADD_CUSTOM_TARGET(translations ALL) - endif() - - foreach(_lang ${LANGUAGES}) - SET(_tempPO "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.po") - set(_srcPO "${CMAKE_CURRENT_SOURCE_DIR}/${_lang}.po") - message(VERBOSE "Generating updated ${_tempPO} from ${_srcPO}") - ADD_CUSTOM_COMMAND(OUTPUT ${_tempPO} - COMMAND msgmerge -o "${_tempPO}" ${EXTRA_MSGMERGE} -s "${_srcPO}" "${_potFile}" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${_lang}.po" ${_potFile} - COMMENT "Updated: ${_tempPO}") - ADD_CUSTOM_TARGET(generate-${_lang}.po DEPENDS ${_tempPO}) - - if(PO_UPDATE) - set(SRC_UPDATE COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_tempPO}" "${_srcPO}") - else() - set(SRC_UPDATE ) - endif() - - SET(_tempMO "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo") - ADD_CUSTOM_COMMAND(OUTPUT "${_tempMO}" - COMMAND msgfmt -o ${_tempMO} ${EXTRA_MSGFMT} ${_tempPO} - ${SRC_UPDATE} - DEPENDS ${_tempPO} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - #COMMENT "Compiled: ${_tempMO}") - ADD_CUSTOM_TARGET(generate-${_lang}.gmo DEPENDS ${_tempMO}) - install(FILES ${_tempMO} DESTINATION "${LOCDIR}/${_lang}/LC_MESSAGES/" RENAME "${PACKAGE}.mo" OPTIONAL) - add_dependencies(translations generate-${_lang}.gmo) - - # mimic the content of the installation folder, for development purposes - set(PG "${CMAKE_CURRENT_BINARY_DIR}/playground") - file(MAKE_DIRECTORY "${PG}") - file(MAKE_DIRECTORY "${PG}/${_lang}/LC_MESSAGES/") - file(CREATE_LINK ${_tempMO} "${PG}/${_lang}/LC_MESSAGES/${PACKAGE}.mo" SYMBOLIC) - - endforeach() - - endif() +if(NOT gettext OR NOT xgettext OR NOT msgmerge OR NOT msgfmt) + message(STATUS "Some of those tools not found, skipping translations! gettext, xgettext, msgmerge, msgfmt") + return() +endif() +set(_potFilePublic "${CMAKE_CURRENT_SOURCE_DIR}/${PACKAGE}.pot") +set(_potFile "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}.pot") +set(_potFileStamp "${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE}.pot.stamp") + +# NOTE: xgettext uses the -f option (and started from project dir so that +# unwanted path information is not leaked) but we also want to track the file +# dependencies, thus building the list here explicitly. +file (STRINGS "POTFILES.in" SRCS_IN) +set(SRCS) +foreach(_src ${SRCS_IN}) + cmake_path(ABSOLUTE_PATH _src BASE_DIRECTORY ${CMAKE_SOURCE_DIR} NORMALIZE) + list(APPEND SRCS ${_src}) +endforeach() + +file(GLOB POS "${CMAKE_CURRENT_SOURCE_DIR}/*.po") +foreach(_src ${POS}) + get_filename_component(_src "${_src}" NAME_WE) + # Ignore junk + if("${_src}" MATCHES "^[a-z][a-z](_[A-Z][A-Z])?$") + list(APPEND LANGUAGES ${_src}) + endif() +endforeach() + +set(XGETTEXT_CMD xgettext -f po/POTFILES.in --from-code=UTF-8 -language=CXX --add-comments=TRANSLATORS: --keyword=_ --keyword=N_ --package-name=${PACKAGE} --copyright-holder="${COPYRIGHT_HOLDER}" --package-version="${VERSION}" --msgid-bugs-address="${BUG_ADDRESS}" -o "${_potFile}" ) + +if(PO_REPLACE OR PO_REPLACE_ONCE) + set(SRC_UPDATE COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_potFile}" "${_potFilePublic}") else() - message(STATUS "Some of those tools not found, skipping translations! gettext, xgettext, msgmerge, msgfmt") + set(SRC_UPDATE ) +endif() +add_custom_command(OUTPUT "${_potFileStamp}" + DEPENDS ${SRCS} + BYPRODUCTS "${_potFile}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + VERBATIM + + COMMAND ${XGETTEXT_CMD} + + ${SRC_UPDATE} + + COMMAND ${CMAKE_COMMAND} -E touch "${_potFileStamp}" + + COMMENT "Extracting translatable messages") + +add_custom_target(update_pot DEPENDS "${_potFileStamp}") +#message(VERBOSE "Adding non-default update_pot target to update ${_potFile}") + +add_custom_target(translations ALL) + +foreach(_lang ${LANGUAGES}) + set(_tempPO "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.po") + set(_srcPO "${CMAKE_CURRENT_SOURCE_DIR}/${_lang}.po") + message(VERBOSE "Generating updated ${_tempPO} from ${_srcPO}") + add_custom_command(OUTPUT ${_tempPO} + COMMAND msgmerge -o "${_tempPO}" ${EXTRA_MSGMERGE} -s "${_srcPO}" "${_potFile}" + #WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${_lang}.po" "${_potFile}" update_pot + #COMMENT "Updated: ${_tempPO}" + VERBATIM) + add_custom_target(generate-${_lang}.po DEPENDS ${_tempPO} ALL) + + if(PO_REPLACE OR PO_REPLACE_ONCE) + set(SRC_UPDATE COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_tempPO}" "${_srcPO}") + message(STATUS "Shall replace: ${_srcPO}") + else() + set(SRC_UPDATE ) + endif() + + set(_tempMO "${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo") + add_custom_command(OUTPUT "${_tempMO}" + COMMAND msgfmt -o ${_tempMO} ${EXTRA_MSGFMT} ${_tempPO} + ${SRC_UPDATE} + DEPENDS ${_tempPO} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + VERBATIM) + add_custom_target(generate-${_lang}.gmo DEPENDS ${_tempMO}) + add_dependencies(translations generate-${_lang}.gmo) + + # Install user products + install(FILES ${_tempMO} DESTINATION "${LOCDIR}/${_lang}/LC_MESSAGES/" RENAME "${PACKAGE}.mo" OPTIONAL) + + # mimic the content of the installation folder, for development purposes + set(PG "${CMAKE_CURRENT_BINARY_DIR}/playground") + file(MAKE_DIRECTORY "${PG}") + file(MAKE_DIRECTORY "${PG}/${_lang}/LC_MESSAGES/") + file(CREATE_LINK ${_tempMO} "${PG}/${_lang}/LC_MESSAGES/${PACKAGE}.mo" SYMBOLIC) + +endforeach() + +if(PO_REPLACE_ONCE) + unset(PO_REPLACE) + unset(PO_REPLACE_ONCE) + unset(PO_REPLACE CACHE) + unset(PO_REPLACE_ONCE CACHE) endif() -# vim: set noexpandtab:ts=2:shiftwidth=2: +# vim: ts=4 shiftwidth=4 et