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

Package:
cmake
Source:
cmake
Description:
cross-platform, open-source make system
Submitter:
Christophe Delahaye
Date:
2026-05-17 10:03:03 UTC
Severity:
normal
Tags:
#1136018#5
Date:
2026-05-08 14:03:38 UTC
From:
To:
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).

#1136018#10
Date:
2026-05-17 10:02:02 UTC
From:
To:
Hi,
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