# How to add a file to the cpack archive that needs to be downloaded first using cmake?

**URL:** <https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939>\
**Category:** Code\
**Created:** [November 23, 2022, 11:00am UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939 "2022-11-23T11:00:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![RaisinTen](https://discourse.cmake.org/user_avatar/discourse.cmake.org/raisinten/32/2945_2.png) [@RaisinTen](https://discourse.cmake.org/u/RaisinTen)\
**Post date:** [November 23, 2022, 11:00am UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939/1 "2022-11-23T11:00:58Z")

</div>

I need a way to include the `esbuild` binary from the `node_modules` directory of my project in the `cpack` archive in a way that `npm ci`, which downloads the `esbuild` package from npm, gets run before the copy operation is started.

From what I learnt, copying a file to the `cpack` archive needs to be done with an `install()` statement, so I have successfully done that using this:

```cmake
set(ESBUILD_CLI "${PROJECT_SOURCE_DIR}/node_modules/esbuild/bin/esbuild")
install(PROGRAMS
  "${ESBUILD_CLI}"
  DESTINATION "${CMAKE_INSTALL_BINDIR}")

```

However, I need to make sure that `${PROJECT_SOURCE_DIR}/node_modules` gets created by running `npm ci` before this code is run. I already have the code to run `npm ci`:

```cmake
find_program(NPM_BIN NAMES npm)

if(NPM_BIN)
  add_custom_command(OUTPUT "${PROJECT_SOURCE_DIR}/node_modules"
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    COMMAND ${NPM_BIN} ci
    DEPENDS ${PROJECT_SOURCE_DIR}/package.json ${PROJECT_SOURCE_DIR}/package-lock.json
    COMMENT "Install Node.js modules")
else()
  message(WARNING "npm: command not found")
endif()

```

but I’m not able to find a way to link these 2 together because the `install()` statement doesn’t accept a `DEPENDS` field where I can pass `${PROJECT_SOURCE_DIR}/node_modules`.

Is there any way of accomplishing what I want, even without using the `install()` statement?

---

<div class="post-metadata">

**Author:** ![giallu](https://discourse.cmake.org/user_avatar/discourse.cmake.org/giallu/32/1938_2.png) [@giallu](https://discourse.cmake.org/u/giallu)\
**Post date:** [November 23, 2022, 2:44pm UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939/2 "2022-11-23T14:44:20Z")

</div>

I believe the trick is that you need to turn the esbuild binary into a target, then it’s trivial to add the dependency. Something like this should work:

```auto
add_custom_target(esbuild_bin ALL
    COMMAND echo "Preparing esbuild binary"
    DEPENDS ${PROJECT_SOURCE_DIR}/node_modules
)

```

---

<div class="post-metadata">

**Author:** ![RaisinTen](https://discourse.cmake.org/user_avatar/discourse.cmake.org/raisinten/32/2945_2.png) [@RaisinTen](https://discourse.cmake.org/u/RaisinTen)\
**Post date:** [November 23, 2022, 2:57pm UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939/3 "2022-11-23T14:57:26Z")

</div>

Right but how do I add the `esbuild_bin` target as a dependency to the `install()`? IIUC, there’s no way of specifying a dependency on `install()` currently.

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)\
**Post date:** [November 23, 2022, 11:19pm UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939/4 "2022-11-23T23:19:35Z")

</div>

It’s not possible today. The [issue tracking it](https://gitlab.kitware.com/cmake/cmake/-/issues/8438) is old.

---

<div class="post-metadata">

**Author:** ![RaisinTen](https://discourse.cmake.org/user_avatar/discourse.cmake.org/raisinten/32/2945_2.png) [@RaisinTen](https://discourse.cmake.org/u/RaisinTen)\
**Post date:** [November 24, 2022, 8:22am UTC](https://discourse.cmake.org/t/how-to-add-a-file-to-the-cpack-archive-that-needs-to-be-downloaded-first-using-cmake/6939/5 "2022-11-24T08:22:23Z")

</div>

13 years old, woah!

Btw, I have come up with a workaround and it seems to be working as expected:

I made a change to the `npm ci` custom command and turned it into a custom target:

```cmake
find_program(NPM_BIN NAMES npm)

if(NPM_BIN)
  add_custom_target(npm-ci
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
    COMMAND ${NPM_BIN} ci
    DEPENDS ${PROJECT_SOURCE_DIR}/package.json ${PROJECT_SOURCE_DIR}/package-lock.json
    COMMENT "Install Node.js modules")
else()
  message(WARNING "npm: command not found")
endif()

```

And finally, I added a dummy `ExternalProject_Add()` that depends on the `npm-ci` target and it looks like this:

```cmake
set(ESBUILD_CLI "${PROJECT_SOURCE_DIR}/node_modules/esbuild/bin/esbuild")

ExternalProject_Add(esbuild
  DEPENDS npm-ci
  DOWNLOAD_COMMAND ""
  BUILD_COMMAND ""
  CONFIGURE_COMMAND ""
  INSTALL_COMMAND "")

install(PROGRAMS
  "${ESBUILD_CLI}"
  DESTINATION "${CMAKE_INSTALL_BINDIR}")

```

So my conclusion is that we can keep `install()`s as is and if we want to add a dependency to it, we can add it to `ExternalProject_Add()`.
