Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake custom target name conflicts between subdirectories

Tags:

c++

cmake

I am writing a game engine and I have a directory called thirdparty where all external libraries my engine uses are placed:

thirdparty/...
          /zlib
          /freetype2
          /SDL2
          /...

So, the engine directory structure looks like:

engine/actors
engine/memory_allocator
engine/renderer
engine/...
engine/thirdparty
engine/thirdparty/CMakeLists.txt
engine/CMakeLists.txt

The engine/CMakeLists.txt:

cmake_minimum_required (VERSION 3.2)

project(Engine)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Werror")
# Include build directory to be able to include generated files:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
file(GLOB GLAD_SOURCES thirdparty/glad/src/glad.c)
file(GLOB ACTOR_SOURCES actors/*.cpp)
file(GLOB LOGIC_SOURCES logic/*.cpp)
file(GLOB UI_SOURCES ui/*.cpp)
set(SOURCES ${GLAD_SOURCES}
            ${ACTOR_SOURCES}
            ${LOGIC_SOURCES}
            ${UI_SOURCES})
add_library(engine SHARED ${SOURCES})

include_directories(thirdparty/glm/)
include_directories(thirdparty/glad/include)
include_directories(thirdparty/tinyxml2/)
include_directories(thirdparty/zlib/)
include_directories(thirdparty/sdl2/SDL2-2.0.5/)
include_directories(./)
add_subdirectory(../../thirdparty thirdparty)

target_link_libraries(engine SDL2)
target_link_libraries(engine tinyxml2)
target_link_libraries(engine zlib)

The engine/thirdparty/CMakeLists.txt:

set(BUILD_CPU_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_EXTRAS OFF CACHE BOOL "" FORCE)
set(BUILD_BULLET2_DEMOS OFF CACHE BOOL "" FORCE)
set(BUILD_UNIT_TESTS OFF CACHE BOOL "" FORCE)
set(FREETYPE_NO_DIST OFF CACHE BOOL "" FORCE)

set(OLD_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "")
# add_subdirectory(bullet3)

set(CMAKE_CXX_FLAGS "${OLD_CXX_FLAGS}")
add_subdirectory(freetype2)

set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
add_subdirectory(tinyxml2)

add_subdirectory(sdl2/SDL2-2.0.5/)

add_subdirectory(zlib)

So, the main engine CMakeLists.txt is in the root directory of the engine's sources and there is another CMakeLists.txt for building third-party libraries in the thirdparty subdirectory of engine's root directory.

The problem is that some of subdirectories in the thirdparty, for example, SDL2 and zlib contain the same target names, added via add_custom_target and so CMake fails to generate the Makefile because of this naming conflicts:

zlib's CMakeLists.txt (in the end):

# uninstall target
if(NOT TARGET uninstall)
  configure_file(
      "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
      "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
      IMMEDIATE @ONLY)

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

SDL2's CMakeLists.txt:

##### Uninstall target #####

configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
    "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
    IMMEDIATE @ONLY)

add_custom_target(uninstall
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)

So the final error is:

CMake Error at /home/user/engine/thirdparty/sdl2/SDL2-2.0.5/CMakeLists.txt:1624 (add_custom_target):
  add_custom_target cannot create target "uninstall" because another target
  with the same name already exists.  The existing target is a custom target
  created in source directory
  "/home/user/engine/thirdparty/zlib".  See
  documentation for policy CMP0002 for more details.

Is there any way to fix this? Perhaps, there is a way to rename these targets by adding any prefix to it so they will never conflict?

like image 267
Victor Polevoy Avatar asked Sep 18 '17 08:09

Victor Polevoy


1 Answers

It mostly depends on which generators you are targeting. A solution that imposes limitations on them is using ALLOW_DUPLICATE_CUSTOM_TARGETS.

As from the documentation:

Allow duplicate custom targets to be created.

It works only for Makefile generators anyway:

For projects that care only about Makefile generators and do not wish to support Xcode or VS IDE generators, one may set this property to true to allow duplicate custom targets.

Otherwise consider to not pack dependencies with the project directly and use the other tools around (like Find*) to get them along with the right paths on the target systems.

like image 93
skypjack Avatar answered Oct 27 '22 00:10

skypjack