Sogartar
Sogartar

Reputation: 2175

CMake: setting the TARGET_FILE generator expression of a custom target

I have a custom target. How do I set it's TARGET_FILE generator expression.

add_custom_target(my_target)
...
# set TARGET_FILE
...
# Use $<TARGET_FILE:my_target>

I tried to set the LOCATION target property hoping that then the TARGET_FILE generator expression would point to it, but that is not the case.

Upvotes: 1

Views: 3475

Answers (2)

cheshirekow
cheshirekow

Reputation: 4907

As another answer pointed out, this cannot be done with add_custom_target, but if what you want is a custom target which has the TARGET_FILE property, then that is possible. The following technique is useful if you have a non-C++ executable which is built via some other mechanism (e.g. perhaps it is just a shell script or maybe it's a self-extracting package, etc).

dummy-main.cc:

int main(int argc, char** argv) {
  return 0;
}

CMakeLists.txt:

# This is the custom command where you generate the custom binary. Maybe it's
# a special compiler for a dynamic language, or maybe you're just creating
# an executable zipfile for python.
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/my-custom-binary.real
         ${CMAKE_CURRENT_BINARY_DIR}/empty.cc
  COMMAND make-my-custom-binary
    -o ${CMAKE_CURRENT_BINARY_DIR}/my-custom-binary.real
  # There is no way to add a file-level dependency between some
  # `add_executable` and this generated file, so we have to generate a
  # stub .cc file just so we can depend on it in `add_executable`
  COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/empty.cc
)

# In cmake, a c++ binary is the only first class citizen. Here, we have a
# custom binary which is generated in some other way and we want cmake to
# treat it like a C++ binary in so much as the target is a name in the global
# namespace of targets and can be used in generator expressions and has
# properties and things. So, first we create a dummy executable:
add_executable(
  my-custom-binary
  dummy-main.cc ${CMAKE_CURRENT_BINARY_DIR}/empty.cc
)

# Then, in the POST_BUILD commands, we delete the executable created by the
# C++ compiler, and replace it with the executable we constructed through
# some other means. 
add_custom_command(
  TARGET my-custom-binary
  POST_BUILD
  COMMAND rm $<TARGET_FILE:my-custom-binary>
  COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/my-custom-binary.real
          $<TARGET_FILE:my-custom-binary>
)

Some other CMakeLists.txt

# Since your custom binary appears to cmake indistinguishable from a C++
# binary, we can use it in the same ways. If our custom binary were a
# code generator, for example, we might do something like this somewhere
# else in our build system
add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
         ${CMAKE_CURRENT_BINARY_DIR}/foo.cc
  DEPENDS foo.in my-custom-binary
  COMMAND $<TARGET_FILE:my-custom-binary>
      -i ${CMAKE_CURRENT_SOURCE_DIR}/foo.in
      -o ${CMAKE_CURRENT_BINARY_DIR} 
)

NOTE: I've verified this technique in a build system, but not this exact code. I may have made typos or other transcription/redaction errors.

Upvotes: 0

KamilCuk
KamilCuk

Reputation: 141708

I have a custom target. How do I set it's TARGET_FILE generator expression.

It is not possible, from add_custom_target:

The target has no output file

ergo it has no TARGET_FILE generator expression.

Upvotes: 0

Related Questions