cmake imported library and precompiled headers

I have a simple CMake project organized like this:

ExternalDependencies
 ->glm
   CMakeLists.txt

MasterFolder
CMakeLists.txt (A)
->src
 CMakeLists.txt (B)
 ->include
  precompiled_header.h

(A) looks like this:

project(coffeecup VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

include(ExternalProject)

ExternalProject_Add(glm_project
        PREFIX glm-lib
        GIT_REPOSITORY "git@github.com:g-truc/glm.git"
        GIT_TAG "24a4befe80171966758983173f381ce1ef6c839f"
        SOURCE_DIR "${PROJECT_SOURCE_DIR}/../ExternalDependencies/glm"
        CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libs/glm"
        CMAKE_CACHE_ARGS    -DBUILD_STATIC_LIBS:BOOL=ON
                            -DBUILD_SHARED_LIBS:BOOL=OFF
                            -DGLM_TEST_ENABLE:BOOL=OFF
        UPDATE_COMMAND ""
        INSTALL_COMMAND ""
        )
ExternalProject_Get_property(glm_project BINARY_DIR)
ExternalProject_Add_Step(glm_project custom_install_glm
        WORKING_DIRECTORY "${BINARY_DIR}"
        COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/libs/glm/lib" "${CMAKE_BINARY_DIR}/libs/glm/include/glm"
        COMMAND ${CMAKE_COMMAND} -E copy glm/glm_static.lib "${CMAKE_BINARY_DIR}/libs/glm/lib"
        COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_SOURCE_DIR}/../ExternalDependencies/glm/glm" "${CMAKE_BINARY_DIR}/libs/glm/include/glm"
        COMMAND ${CMAKE_COMMAND} -E remove -f  "${CMAKE_BINARY_DIR}/libs/glm/include/glm/CMakeLists.txt"
        DEPENDEES build
        COMMENT           "custom installation process glm_project"
        ALWAYS            TRUE
        )

SET(CMAKE_CONFIGURATION_TYPES "Debug;Release")

file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/libs/glm/include")


add_library (glm STATIC IMPORTED)
set_target_properties (glm PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/libs/glm/lib/glm_static.lib)
target_include_directories(glm INTERFACE ${CMAKE_BINARY_DIR}/libs/glm/include)



add_dependencies(glm glm_project)
add_subdirectory(src)

in the (B) CMakeLists.txt:

list(APPEND EXTERNAL_DEPENDENCIES_INCLUDES
        ../../ExternalDependencies/VulkanMemoryAllocator/src
        )

add_executable(coffeecup
        include/PrecompiledHeader.h
        Window.cpp )
set_target_properties(coffeecup PROPERTIES DEBUG_POSTFIX "d")

target_include_directories(coffeecup 
        PUBLIC 
           include
        )

target_link_libraries(coffeecup 
        PUBLIC 
           glm
        )

target_precompile_headers(coffeecup
        PUBLIC
            include/PrecompiledHeader.h
        )

and finally, the precompiled header looks like this:

#pragma once

// >>> GLM <<<
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/quaternion.hpp>

// >>> STL <<<
#include <unordered_map>

So the problem here is that the precompiled header is actually built before the static library GLM so it only works if I previously build my GLM library How can I force the precompiled header to be built only if the library is there? I’m missing something as I am really new with CMake, probably there is an issue with the usage of PRIVATE|INTERFACE|PUBLIC

The first thing I would change is

-ExternalProject_Add_Step(glm_project custom_install_glm
+ExternalProject_Add_Step(glm_project install

because the documentation of ExternalProject_Add_Step says:

The specified <step> must not be one of the pre-defined steps (mkdir , download , update , patch , configure , build , install or test )

Then, you can use ExternalProject_Add_StepTargets to create a CMake target that “represents” installing glm and make your own target depend on it.

I hope this helps!

Sorry but I do not understand…the documentation says must not be
in fact, if I do what you say I have an error

CMake Error at ...cmake-3.17/Modules/ExternalProject.cmake:2224 (add_custom_command): 
  Attempt to add a custom rule to output
...
which already has a custom rule.

what am I missing?

My bad, I completely misread the documentation :sweat_smile:

Please skip that part and focus on ExternalProject_Add_StepTargets only.

no problem…so yes looking on the documentation for ExternalProject_Add_StepTargets
It seems there is a dependence system
But how can I make my precompiled header dependent on the library?

I would guess something like this:

# In (A) CMakeLists.txt:
ExternalProject_Add_StepTargets(glm_project custom_install_glm)

# In (B) CMakeLists.txt:
add_dependencies(coffeecup glm_project-custom_install_glm)