How to get the path of a not imported target?

with this code

if(TARGET gtest-tidy-mwe)
    # deprecated: get_target_property(TGT_LOCATION gtest-tidy-mwe LOCATION)
    set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)
    message(STATUS "set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)")
    message(WARNING "TGT_LOCATION: ${TGT_LOCATION}")
endif()

I get this output:

-- set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)
CMake Warning at CMakeLists.txt:66 (message):
  TGT_LOCATION: $<TARGET_FILE:gtest-tidy-mwe>

but this works fine?

# Additional command which will run after the above from a different directory
add_custom_command(TARGET gtest-tidy-mwe
      POST_BUILD
      COMMAND md5sum $<TARGET_FILE:gtest-tidy-mwe> > gtest-tidy-mwe.md5
      BYPRODUCTS ${CMAKE_BINARY_DIR}/verify/gtest-tidy-mwe.md5
      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/verify
)

see too unable to get target location - #6 by Angew

You can’t reliably get the location of a target at configure time. For a multi-config generator, the location depends on the configuration, and the configuration is only selected at build time.

Don’t use the LOCATION target property. It should be considered an old historical hangover from before generator expressions existed. It cannot give you the location of the binary in a multi-config world.

The message() command doesn’t and can never understand generator expressions because it executes at configure time. By definition, generator expressions can only be evaluated at generation time, which occurs after the configure stage has finished.

This does also not work?

set(cmd [=[
        message(STATUS "DIR: $<SHELL_PATH:$<TARGET_FILE_DIR:gtest-tidy-mwe>>")
    ]=])
cmake_language(EVAL CODE ${cmd})

Is there no way to get this value in a cmake variable?

with this code:

if(TARGET gtest-tidy-mwe)
    # deprecated: get_target_property(TGT_LOCATION gtest-tidy-mwe LOCATION)
    set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)
    # set(cmd [=[
    #     message(STATUS "DIR: $<SHELL_PATH:$<TARGET_FILE_DIR:gtest-tidy-mwe>>")
    # ]=])
    # cmake_language(EVAL CODE ${cmd})
    message(STATUS "set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)")

    file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/verify/target_file.txt
         CONTENT $<SHELL_PATH:$<TARGET_FILE:gtest-tidy-mwe>>)
    if(EXISTS ${CMAKE_BINARY_DIR}/verify/target_file.txt)
        file(READ ${CMAKE_BINARY_DIR}/verify/target_file.txt TGT_LOCATION)
        message(WARNING "TGT_LOCATION: ${TGT_LOCATION}")
    endif()
endif()

I get this strange behaviour:

bash-5.2$ rm verify/*
bash-5.2$ cmake .
-- target=util
   linkage=SHARED
   source=/Users/clausklein/Workspace/cpp/test/util
   include=/Users/clausklein/Workspace/cpp/test
   header=/Users/clausklein/Workspace/cpp/test/util/util.h
-- set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)
-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: /Users/clausklein/Workspace/cpp/test/build/default
bash-5.2$ cmake .
-- target=util
   linkage=SHARED
   source=/Users/clausklein/Workspace/cpp/test/util
   include=/Users/clausklein/Workspace/cpp/test
   header=/Users/clausklein/Workspace/cpp/test/util/util.h
-- set(TGT_LOCATION $<TARGET_FILE:gtest-tidy-mwe>)
CMake Warning at CMakeLists.txt:83 (message):
  TGT_LOCATION:
  /Users/clausklein/Workspace/cpp/test/build/default/gtest-tidy-mwe


-- Configuring done (0.3s)
-- Generating done (0.1s)
-- Build files have been written to: /Users/clausklein/Workspace/cpp/test/build/default
bash-5.2$ 

See my last reply:

If you pass a string to message() and it contains generator expressions, they won’t be evaluated.

Also, for file(GENERATE), it doesn’t write out the file immediately. It essentially schedules the file to be written during the generation phase. You can’t read it at configure time (if you try to, at best you’ll be reading the file that was generated in the previous run).