build: Repair and reduce the CMake build dependency graph

A funny thing happened while refactoring the function argument parsing
in the `PNGGenConfig` module: the processing of dependencies inside
the CMake function `generate_copy` got fixed, thanks to an inadvertent
typo correction!

Going down the rabbit hole, we uncovered two issues:

 1. A typo in `scripts/cmake/PNGGenConfig.cmake` caused a dependency
    declaration to disappear, disrupting the graph. Fortunately, this
    disruption was being mitigated by an additional set of (redundant)
    symbolic target declarations that kept the CMake build going.

 2. The exact string matching inside `scripts/cmake/gensrc.cmake.in`
    imposed an artificial limitation, disallowing the use of absolute
    file paths.

The typo correction in (1), and the use of regex matching instead of
exact string matching in (2), allowed us to use absolute file paths
in the main CMake file, consistently, thus allowing CMake to recognize
them as uniquely-identifiable nodes in the dependency graph. There
should be no further need to have extra symbolic targets for proper
node identification.

In the end, we shaved off the redundant symbolic target declarations,
retaining only `png_genfiles` and `png_genprebuilt`.
This commit is contained in:
Cosmin Truta 2025-05-29 22:55:00 +03:00
parent f04c457a51
commit 0cc6436ef5
3 changed files with 57 additions and 105 deletions

View File

@ -476,20 +476,16 @@ else()
NEWLINE_STYLE LF)
# Generate scripts/pnglibconf.h
generate_source(OUTPUT "scripts/pnglibconf.c"
generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/options.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
add_custom_target(png_scripts_pnglibconf_c
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c")
# Generate pnglibconf.c
generate_source(OUTPUT "pnglibconf.c"
generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
"${CMAKE_CURRENT_BINARY_DIR}/scripts/options.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
add_custom_target(pnglibconf_c
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c")
if(PNG_PREFIX)
set(PNGLIBCONF_H_EXTRA_DEPENDS
@ -500,85 +496,53 @@ else()
endif()
generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
DEPENDS pnglibconf_c)
add_custom_target(pnglibconf_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
# Generate pnglibconf.h
generate_source(OUTPUT "pnglibconf.h"
generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
pnglibconf_out
${PNGLIBCONF_H_EXTRA_DEPENDS})
add_custom_target(pnglibconf_h
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
pnglibconf_h)
add_custom_target(png_scripts_intprefix_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
pnglibconf_out)
add_custom_target(png_scripts_prefix_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out")
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
# Generate pngprefix.h
generate_source(OUTPUT "pngprefix.h"
generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h"
DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS})
add_custom_target(pngprefix_h
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
pnglibconf_h)
add_custom_target(png_scripts_sym_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out")
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt")
add_custom_target(png_scripts_symbols_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out")
generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
"${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
pnglibconf_h)
add_custom_target(png_scripts_vers_out
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
DEPENDS png_scripts_symbols_out
"${CMAKE_CURRENT_BINARY_DIR}/scripts/checksym.awk"
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/checksym.awk"
"${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
add_custom_target(png_scripts_symbols_chk
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
DEPENDS png_scripts_sym_out)
generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
DEPENDS png_scripts_vers_out)
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
add_custom_target(png_genvers
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
add_custom_target(png_gensym
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
add_custom_target(png_genprebuilt
COMMAND "${CMAKE_COMMAND}"
@ -589,31 +553,18 @@ else()
# A single target handles generation of all generated files.
add_custom_target(png_genfiles
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
png_gensym
"${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
png_genvers
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
pnglibconf_c
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
pnglibconf_h
"${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
pnglibconf_out
"${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h"
pngprefix_h
"${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
png_scripts_intprefix_out
"${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c"
png_scripts_pnglibconf_c
"${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
png_scripts_prefix_out
"${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
png_scripts_sym_out
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
png_scripts_symbols_chk
"${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
png_scripts_symbols_out
"${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
png_scripts_vers_out)
"${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
endif()
# List the source code files.

View File

@ -18,21 +18,21 @@ function(generate_chk)
set(options)
set(oneValueArgs INPUT OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GC_INPUT)
cmake_parse_arguments(_GENCHK "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GENCHK_INPUT)
message(FATAL_ERROR "generate_chk: Missing INPUT argument")
endif()
if(NOT _GC_OUTPUT)
if(NOT _GENCHK_OUTPUT)
message(FATAL_ERROR "generate_chk: Missing OUTPUT argument")
endif()
# Run genchk.cmake to generate the .chk file.
add_custom_command(OUTPUT "${_GC_OUTPUT}"
add_custom_command(OUTPUT "${_GENCHK_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DINPUT=${_GC_INPUT}"
"-DOUTPUT=${_GC_OUTPUT}"
"-DINPUT=${_GENCHK_INPUT}"
"-DOUTPUT=${_GENCHK_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genchk.cmake"
DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS}
DEPENDS "${_GENCHK_INPUT}" ${_GENCHK_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
@ -42,21 +42,21 @@ function(generate_out)
set(options)
set(oneValueArgs INPUT OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GO_INPUT)
cmake_parse_arguments(_GENOUT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GENOUT_INPUT)
message(FATAL_ERROR "generate_out: Missing INPUT argument")
endif()
if(NOT _GO_OUTPUT)
if(NOT _GENOUT_OUTPUT)
message(FATAL_ERROR "generate_out: Missing OUTPUT argument")
endif()
# Run genout.cmake to generate the .out file.
add_custom_command(OUTPUT "${_GO_OUTPUT}"
add_custom_command(OUTPUT "${_GENOUT_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DINPUT=${_GO_INPUT}"
"-DOUTPUT=${_GO_OUTPUT}"
"-DINPUT=${_GENOUT_INPUT}"
"-DOUTPUT=${_GENOUT_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genout.cmake"
DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS}
DEPENDS "${_GENOUT_INPUT}" ${_GENOUT_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
@ -66,17 +66,17 @@ function(generate_source)
set(options)
set(oneValueArgs OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GSO_OUTPUT)
cmake_parse_arguments(_GENSRC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GENSRC_OUTPUT)
message(FATAL_ERROR "generate_source: Missing OUTPUT argument")
endif()
# Run gensrc.cmake to generate the source file.
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}"
add_custom_command(OUTPUT "${_GENSRC_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
"-DOUTPUT=${_GSO_OUTPUT}"
"-DOUTPUT=${_GENSRC_OUTPUT}"
-P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake"
DEPENDS ${_GSO_DEPENDS}
DEPENDS ${_GENSRC_DEPENDS}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endfunction()
@ -86,19 +86,19 @@ function(generate_copy)
set(options)
set(oneValueArgs INPUT OUTPUT)
set(multiValueArgs DEPENDS)
cmake_parse_arguments(_GCO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GCO_INPUT)
cmake_parse_arguments(_GENCPY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT _GENCPY_INPUT)
message(FATAL_ERROR "generate_copy: Missing INPUT argument")
endif()
if(NOT _GCO_OUTPUT)
if(NOT _GENCPY_OUTPUT)
message(FATAL_ERROR "generate_copy: Missing OUTPUT argument")
endif()
# Make a forced file copy, overwriting any pre-existing output file.
add_custom_command(OUTPUT "${_GCO_OUTPUT}"
add_custom_command(OUTPUT "${_GENCPY_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
-E remove "${_GCO_OUTPUT}"
-E remove "${_GENCPY_OUTPUT}"
COMMAND "${CMAKE_COMMAND}"
-E copy "${_GCO_INPUT}" "${_GCO_OUTPUT}"
DEPENDS "${source}" ${_GCO_DEPENDS})
-E copy "${_GENCPY_INPUT}" "${_GENCPY_OUTPUT}"
DEPENDS "${_GENCPY_INPUT}" ${_GENCPY_DEPENDS})
endfunction()

View File

@ -21,8 +21,8 @@ set(DFA_XTRA "@DFA_XTRA@")
set(PNG_PREFIX "@PNG_PREFIX@")
set(PNGLIB_VERSION "@PNGLIB_VERSION@")
if(OUTPUT STREQUAL "scripts/pnglibconf.c")
# Generate scripts/pnglibconf.c
if(OUTPUT MATCHES "(scripts/pnglibconf\\.c)\$")
# Generate "${BINDIR}/scripts/pnglibconf.c"
file(REMOVE "${BINDIR}/pnglibconf.tf6" "${BINDIR}/pnglibconf.tf7")
@ -49,8 +49,8 @@ if(OUTPUT STREQUAL "scripts/pnglibconf.c")
file(MAKE_DIRECTORY "${BINDIR}/scripts")
file(RENAME "pnglibconf.tf7" "${BINDIR}/scripts/pnglibconf.c")
elseif(OUTPUT STREQUAL "pnglibconf.c")
# Generate pnglibconf.c
elseif(OUTPUT MATCHES "(pnglibconf\\.c)\$")
# Generate "${BINDIR}/pnglibconf.c"
file(REMOVE "${BINDIR}/pnglibconf.tf4" "${BINDIR}/pnglibconf.tf5")
@ -76,10 +76,10 @@ elseif(OUTPUT STREQUAL "pnglibconf.c")
file(MAKE_DIRECTORY "${BINDIR}/scripts")
file(RENAME "pnglibconf.tf5" "${BINDIR}/pnglibconf.c")
elseif(OUTPUT STREQUAL "pnglibconf.h")
# Generate pnglibconf.h
elseif(OUTPUT MATCHES "(pnglibconf\\.h)\$")
# Generate "${BINDIR}/pnglibconf.h"
file(REMOVE "${BINDIR}/${OUTPUT}")
file(REMOVE "${OUTPUT}")
if(PNG_PREFIX)
file(REMOVE "pnglibconf.tf8")
@ -95,20 +95,21 @@ elseif(OUTPUT STREQUAL "pnglibconf.h")
message(FATAL_ERROR "Failed to generate pnglibconf.tf8")
endif()
file(RENAME "pnglibconf.tf8" "${BINDIR}/${OUTPUT}")
file(RENAME "pnglibconf.tf8" "${OUTPUT}")
else()
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${BINDIR}/pnglibconf.out"
"${BINDIR}/${OUTPUT}"
execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "pnglibconf.out"
"${OUTPUT}"
WORKING_DIRECTORY "${BINDIR}"
RESULT_VARIABLE COPY_FAIL)
if(COPY_FAIL)
message(FATAL_ERROR "Failed to create pnglibconf.h")
endif()
endif()
elseif(OUTPUT STREQUAL "pngprefix.h")
# Generate pngprefix.h
elseif(OUTPUT MATCHES "(pngprefix\\.h)\$")
# Generate "${BINDIR}/pngprefix.h"
file(REMOVE "${BINDIR}/${OUTPUT}")
file(REMOVE "${OUTPUT}")
if(PNG_PREFIX)
file(REMOVE "pngprefix.tf1")
@ -122,12 +123,12 @@ elseif(OUTPUT STREQUAL "pngprefix.h")
message(FATAL_ERROR "Failed to generate pngprefix.tf1")
endif()
file(RENAME "pngprefix.tf1" "${BINDIR}/${OUTPUT}")
file(RENAME "pngprefix.tf1" "${OUTPUT}")
else()
file(WRITE "${BINDIR}/${OUTPUT}" "/* No libpng symbol prefix configured. */")
file(WRITE "${OUTPUT}" "/* No libpng symbol prefix configured. */")
endif()
elseif(OUTPUT STREQUAL "scripts/pnglibconf.h.prebuilt")
elseif(OUTPUT MATCHES "(scripts/pnglibconf\\.h\\.prebuilt)\$")
# Generate scripts/pnglibconf.h.prebuilt (fails build)
message(STATUS "Attempting to build scripts/pnglibconf.h.prebuilt")