cmakemercurialsubrepos

How to deal with target name conflicts between Mercurial repositories and subrepositories?


My Mercurial repository repo1 has a custom target named foo; never mind what it does. I also have another repository repo2, which which I want to use as a subrepo of repo1. repo2 is developed in a similar fashion to repo1, and also has a custom target named foo, doing about the same thing (but just for the repo2 directory of course).

If I try to run CMake for repo1 with add_subdirectory(relative/path/to/repo2) in the CMakeLists.txt, I get:

CMake Error at CMakeLists.txt:123 (add_custom_target):
  add_custom_target cannot create target "foo" because another target with
  the same name already exists.  The existing target is a custom target
  created in source directory

I suppose I could just prefix the custom target names with the repository names, but that seems like a crude solution to this problem; and I kind of like the fact that make foo does the same thing, conceptually, both in repo1 and in repo2. So is there anything smarter I can do here?


Solution

  • Approach depends on what you expect from

    make foo
    
    1. Building target only for current project. That is, being run from directory of project1, make foo should build target for this project. Same for project2.

      In that case, use ExternalProject_Add instead of add_subdirectory for bind projects together.

    2. Building targets for both projects.

      Usually such targets are "project-wide actions", like make uninstall or make test.

      In that case, before adding the target into the project, you need to check whether target exists and take appropriate actions:

      if(NOT TARGET foo)
          <create target foo>
      endif()
      <append-new-actions-to-foo>
      

      Steps "create" and "append" depend on target type.

      E.g., classic uninstall target automatically process all subprojects via reading install_manifest.txt file:

      if(NOT TARGET uninstall)
          add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
      endif()
      

      For general case, you may create per-project targets and attach them via add_dependencies to the "shared" target:

      if(NOT TARGET foo)
          add_custom_target(foo)
      endif()
      add_custom_target(foo_${CMAKE_PROJECT_NAME} <do-something>)
      add_dependencies(foo foo_${CMAKE_PROJECT_NAME})