Bug#1136018: cmake: corruption of link command line by a custom command

2026-05-17 Thread Timo Röhling

Control: tags -1 + wontfix
Control: notfound -1 3.31.6-2

Hi,

On Fri, 08 May 2026 16:03:38 +0200 Christophe Delahaye 
 wrote:
  # !!? This command make the application object file disappear in the 
  linker command line, leaving only the libraries.  So the linker 
  rightly protests about a missing main() symbol.

#  add_custom_command(
#   OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.pdf"
#   COMMAND doxygen ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.conf
#   COMMAND sh -c 'cd dox_svn-umilo/latex && ${PDFLATEX_COMPILER} 
refman.tex'
#   COMMAND mv ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo/latex/refman.pdf 
${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.pdf
#   MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/svn-umilo.cpp
#   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.conf
#   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
#   COMMENT "Génération de la documentation Doxygen au format HTML et LaTeX, et 
composition du LaTeX en PDF"
#  )
The issue is the MAIN_DEPENDENCY, which does not behave as you expect. 
The documentation [1] says:


 MAIN_DEPENDENCY
Specify the primary input source file to the command.
[...]
Each source file may have at most one command specifying it as its
main dependency. A compile command (i.e. for a library or an
executable) counts as an implicit main dependency which gets
silently overwritten by a custom command specification.

The reason for this design is the Visual Studio
Code Generator, which attaches rules to sources instead of outputs.

The correct solution in your case is to put everything under DEPENDS
and not use MAIN_DEPENDENCY at all.


Cheers
Timo


[1] https://cmake.org/cmake/help/latest/command/add_custom_command.html


--
⢀⣴⠾⠻⢶⣦⠀   ╭╮
⣾⠁⢠⠒⠀⣿⡁   │ Timo Röhling   │
⢿⡄⠘⠷⠚⠋⠀   │ 9B03 EBB9 8300 DF97 C2B1  23BF CC8C 6BDD 1403 F4CA │
⠈⠳⣄   ╰╯


signature.asc
Description: PGP signature


Bug#1136018: cmake: corruption of link command line by a custom command

2026-05-08 Thread Christophe Delahaye
Package: cmake
Version: 3.31.6-2
Severity: normal

Dear Maintainer,

Let us consider a simple program that use the Subversion libraries. Here is its 
CMakeLists.txt, reduced for this bug report:

cmake_minimum_required(VERSION 3.28..3.31)
project(svn-umilo VERSION 1.1.3 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
include(GNUInstallDirs)

find_package(PkgConfig REQUIRED)
# ce pkg_check_modules ressemble beaucoup à la macro des autotools
pkg_check_modules(SVNUMILO REQUIRED libsvn_ra libsvn_repos libsvn_client 
libsvn_subr libarchive liblog4cxx)

find_package(Doxygen)
if (${DOXYGEN_FOUND})
  find_package(LATEX REQUIRED COMPONENTS PDFLATEX)
  configure_file(dox_svn-umilo.conf.cmake-in dox_svn-umilo.conf @ONLY)
endif()
  
add_executable(svn-umilo svn-umilo.cpp)
target_include_directories(svn-umilo AFTER PRIVATE ${SVNUMILO_INCLUDE_DIRS})
target_link_libraries(svn-umilo ${SVNUMILO_LINK_LIBRARIES})
target_link_directories(svn-umilo PRIVATE ${SVNUMILO_LIBRARY_DIRS})

# ... Other documentation targets cut for this report ...
# Autre documentation :
if (${DOXYGEN_FOUND})
  # !!? This command make the application object file disappear in the linker 
command line, leaving only the libraries.  So the linker rightly protests about 
a missing main() symbol.
#  add_custom_command(
#   OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.pdf"
#   COMMAND doxygen ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.conf
#   COMMAND sh -c 'cd dox_svn-umilo/latex && ${PDFLATEX_COMPILER} 
refman.tex'
#   COMMAND mv ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo/latex/refman.pdf 
${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.pdf
#   MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/svn-umilo.cpp
#   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.conf
#   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
#   COMMENT "Génération de la documentation Doxygen au format HTML et 
LaTeX, et composition du LaTeX en PDF"
#  )
  add_custom_target(dox_svn-umilo.pdf DEPENDS 
${CMAKE_CURRENT_BINARY_DIR}/dox_svn-umilo.pdf)
endif()

Let us configure and build this:
cmake -S . -B tmp
make -C tmp VERBOSE=1 svn-umilo

At this point all is fine. Now enable the commented-out add_custom_command() 
for Doxygen and rebuild:
make -C tmp VERBOSE=1 svn-umilo
Now the linker fails: "undefined reference to main".

Indeed, wdiff applied to the 2 command lines shows that the application object 
file "CMakeFiles/svn-umilo.dir/svn-umilo.cpp.o" is missing in the 2nd run. So 
something that processes the add_custom_command() command modifies the build 
information of the unrelated target defined by add_program().

This bus also applies to cmake 3.28 as found in Ubuntu 24.04 LTS (Noble).


-- System Information:
Debian Release: 13.4
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 6.12.85+deb13-amd64 (SMP w/4 CPU threads; PREEMPT)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages cmake depends on:
ii  cmake-data   3.31.6-2
ii  libarchive13t64  3.7.4-4
ii  libc62.41-12+deb13u2
ii  libcurl4t64  8.14.1-2+deb13u2
ii  libexpat12.7.1-2
ii  libgcc-s114.2.0-19
ii  libjsoncpp26 1.9.6-3
ii  librhash11.4.5-1
ii  libstdc++6   14.2.0-19
ii  libuv1t641.50.0-2
ii  procps   2:4.0.4-9
ii  zlib1g   1:1.3.dfsg+really1.3.1-1+b1

Versions of packages cmake recommends:
ii  gcc   4:14.2.0-1
ii  make  4.4.1-2

Versions of packages cmake suggests:
ii  cmake-doc3.31.6-2
pn  cmake-format 
ii  elpa-cmake-mode  4.0.1+ds-1
ii  ninja-build  1.12.1-1

-- no debconf information