# ExternalProject\_Add commands with wildcard

**URL:** https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289
**Category:** Code
**Tags:** os:linux, gen:makefiles, gen:ninja
**Created:** [December 30, 2024, 5:38pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289 "2024-12-30T17:38:47Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![DKLind](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dklind/32/526_2.png) [@DKLind](https://discourse.cmake.org/u/DKLind)
#### Post date: [December 30, 2024, 5:38pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/1 "2024-12-30T17:38:47Z")

</div>

I have a little problem with ExternalProject\_Add when I try to use a command with a wildcard ‘\*’. The command statement is generated with quotes around the wildcard statement which causes the command to fail.  
For example:

```auto
    INSTALL_COMMAND
        ${CMAKE_COMMAND} -E make_directory
            ${CMAKE_CURRENT_BINARY_DIR}/install/usr/include
    COMMAND
        ${CMAKE_COMMAND} -E copy
            libexfat/*.h
            ${CMAKE_CURRENT_BINARY_DIR}/install/usr/include

```

The generated command is:

```auto
build exfat/src/exfat-stamp/exfat-install | ${cmake_ninja_workdir}exfat/src/exfat-stamp/exfat-install: CUSTOM_COMMAND exfat/src/exfat-stamp/exfat-build
  COMMAND = cd /home/users/dlind/packages/build-armv5te/exfat/src/exfat && /usr/bin/cmake -E make_directory /home/users/dlind/packages/build-armv5te/exfat/install/usr/include && /usr/bin/cmake -E copy "libexfat/*.h"/home/users/dlind/packages/build-armv5te/exfat/install/usr/include && /usr/bin/cmake -E touch /home/users/dlind/packages/build-armv5te/exfat/src/exfat-stamp/exfat-install
  DESC = Performing install step for 'exfat'
  pool = console
  restat = 1

```

Notice

```auto
/usr/bin/cmake -E copy "libexfat/*.h" /home/dlind/packages/build-armv5te/exfat/install/usr/include

```

This causes the copy command to fail. If I edit the ninja project file and remove the quotes the command works.  
This behavior happens with any part of ExternalProject\_Add when a asterisk is used. The command gets quoted.  
Is there another way to specify an asterisk? There isn’t an $\<ASTERISK\> equivalent of $\<SEMICOLON\>.

---

<div class="post-metadata">

### Author: ![DKLind](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dklind/32/526_2.png) [@DKLind](https://discourse.cmake.org/u/DKLind)
#### Post date: [December 30, 2024, 6:16pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/2 "2024-12-30T18:16:31Z")

</div>

This is really annoying. I can use add\_custom\_target and the output is generated without quotes.

```auto
add_custom_target(test-target
    COMMAND
        ${CMAKE_COMMAND} -E copy
            libexfat/*.h
            ${CMAKE_CURRENT_BINARY_DIR}/install/usr/include
)

```

```auto
build exfat/CMakeFiles/test-target | ${cmake_ninja_workdir}exfat/CMakeFiles/test-target: CUSTOM_COMMAND
  COMMAND = cd /home/users/dlind/packages/build-armv5te/exfat && /usr/bin/cmake -E copy libexfat/*.h /fast/users/dlind/pss/packages/build-armv5te/exfat/install/usr/include

```

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [December 30, 2024, 9:08pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/3 "2024-12-30T21:08:51Z")

</div>

Wildcard expansion is a shell feature. You are assuming that `ExternalProject_Add()` and `add_custom_target()` use a shell to execute their command(s), but this is not guaranteed to be the case. The `add_custom_target()` command’s documentation alludes to this, but doesn’t make this as clear as it could. The fact that `add_custom_target()` appears to expand your wildcard correctly should be seen as an implementation detail that you should not rely on.

If you want shell expansion, you need to invoke a shell explicitly as your COMMAND. Note that your command is platform-specific if it relies on wildcard expansion.

For the particular example you’ve given, you can create a CMake script that contains a `file(COPY)` command with appropriate arguments to do the copying. This would replace the shell wildcard expansion with pattern matching performed by the `file()` command. This would be platform independent and would avoid the problem you’ve highlighted.

---

<div class="post-metadata">

### Author: ![DKLind](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dklind/32/526_2.png) [@DKLind](https://discourse.cmake.org/u/DKLind)
#### Post date: [January 3, 2025, 5:34pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/4 "2025-01-03T17:34:25Z")

</div>

There are two phases to CMake.

1. The configure phase: When CMake is executed and the -G\<generator\> creates the build phase files (ninja project files, makefiles, etc.)
2. The build phase: When the generator is executed (ninja, make, etc.)

In this case, there is a CMake bug with the configure phase when using `ExternalProject_Add()`. When an asterisk is used in any step, the generator files are created by CMake with quotes around the command with the asterisk. This causes the build phase to fail because the shell doesn’t know how to handle a command with quotes.

Doing a manual execution of this command:  
`/usr/bin/cmake -E copy "libexfat/*.h" /home/users/dlind/packages/build-armv5te/exfat/install/usr/include`

Produces:  
`Error copying file "libexfat/*.h" to "/home/users/dlind/packages/build-armv5te/exfat/install/usr/include"`

If I replace using “cmake -E copy” with the shell "cp’:  
`cp "libexfat/*.h" /home/users/dlind/packages/build-armv5te/exfat/install/usr/include`

Produces:  
`cp: cannot stat 'libexfat/*.h': No such file or directory`

In both cases the failure is because of the quotes. Remove the quotes and the command at least attempts to copy the files specified.

BTW, you can’t use `file(COPY)` with either `ExternalProject_Add()` COMMANDs or `add_custom_target()` COMMANDs. These commands are executed during the build phase.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [January 5, 2025, 9:29pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/5 "2025-01-05T21:29:00Z")

</div>

> [@DKLind](#):
>
> BTW, you can’t use `file(COPY)` with either `ExternalProject_Add()` COMMANDs or `add_custom_target()` COMMANDs. These commands are executed during the build phase.

That’s why I said:

> … you can create a CMake script that contains a `file(COPY)` command…

You then use something like `COMMAND ${CMAKE_COMMAND} -P that-script-file` to run it at build time in the install step of your `ExternalProject_Add()` command.

---

<div class="post-metadata">

### Author: ![DKLind](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dklind/32/526_2.png) [@DKLind](https://discourse.cmake.org/u/DKLind)
#### Post date: [January 7, 2025, 2:32pm UTC](https://discourse.cmake.org/t/externalproject-add-commands-with-wildcard/13289/6 "2025-01-07T14:32:03Z")

</div>

> [@craig.scott](#):
>
> CMake script

Sorry my mistake, I didn’t see the `CMake script` part of your post.  
If I can find the time, I would like to look into a patch that will fix the issue.
