Merge bitcoin/bitcoin#32773: cmake: Create subdirectories in build tree in advance

76dae5d6911b600fafa3a417a740f14b299284f3 cmake: Replace recursive globbing with explicit globbing in folders (Hennadii Stepanov)
88d909257104124bee3fc810f7fa32e5802b92fe cmake: Create subdirectories in build tree in advance (Hennadii Stepanov)

Pull request description:

  While reviewing https://github.com/bitcoin/bitcoin/pull/32697, I noticed that symlink creation fails when the target subdirectory does not exist. In such cases, `file(CREATE_LINK ... COPY_ON_ERROR SYMBOLIC)` falls back to copying, which implicitly creates the required path. As a result, a single file is copied instead of symlinked for subdirectories in `test/functional`.

  This PR ensures that necessary subdirectories are created in advance, so that subsequent symlink creation does not fail due to missing paths.

  For example:
  - on the master branch:
  ```
  $ cmake -B build
  $ ls -l build/test/functional/mocks/
  total 8
  -rwxrwxr-x 1 hebasto hebasto 2683 Jul  3 14:11 invalid_signer.py
  lrwxrwxrwx 1 hebasto hebasto   64 Jul  3 14:11 multi_signers.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/multi_signers.py
  lrwxrwxrwx 1 hebasto hebasto   60 Jul  3 14:11 no_signer.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/no_signer.py
  lrwxrwxrwx 1 hebasto hebasto   57 Jul  3 14:11 signer.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/signer.py
  ```
  - with this PR:
  ```
  $ cmake -B build
  $ ls -l build/test/functional/mocks/
  total 4
  lrwxrwxrwx 1 hebasto hebasto 65 Jul  3 13:51 invalid_signer.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/invalid_signer.py
  lrwxrwxrwx 1 hebasto hebasto 64 Jul  3 13:51 multi_signers.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/multi_signers.py
  lrwxrwxrwx 1 hebasto hebasto 60 Jul  3 13:51 no_signer.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/no_signer.py
  lrwxrwxrwx 1 hebasto hebasto 57 Jul  3 13:51 signer.py -> /home/hebasto/dev/bitcoin/test/functional/mocks/signer.py
  ```

ACKs for top commit:
  m3dwards:
    ACK 76dae5d6911b600fafa3a417a740f14b299284f3
  sedited:
    ACK 76dae5d6911b600fafa3a417a740f14b299284f3
  janb84:
    re ACK 76dae5d6911b600fafa3a417a740f14b299284f3

Tree-SHA512: a720a68752c72390b9452b192b06d09e41cac1080d32cfe3c2caabb65949626771e0709e7193f69677bd24a3c747e368c2323d9c857d4aa97e1890cc463850ed
This commit is contained in:
merge-script 2026-02-09 11:03:58 +00:00
commit 7e5e0b20ea
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1

View File

@ -34,17 +34,65 @@ endfunction()
create_test_config()
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fuzz)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/util)
file(GLOB_RECURSE functional_tests RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} functional/*)
foreach(script ${functional_tests} fuzz/test_runner.py)
if(CMAKE_HOST_WIN32)
set(symlink)
else()
set(symlink SYMBOLIC)
endif()
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${script} ${CMAKE_CURRENT_BINARY_DIR}/${script} COPY_ON_ERROR ${symlink})
endforeach()
unset(functional_tests)
function(create_test_directory_links)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional)
file(GLOB functional
LIST_DIRECTORIES FALSE
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
functional/*.html
functional/*.py
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional/data)
file(GLOB functional_data
LIST_DIRECTORIES FALSE
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
functional/data/*.json
functional/data/*.py
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional/mocks)
file(GLOB functional_mocks
LIST_DIRECTORIES FALSE
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
functional/mocks/*.py
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional/test_framework)
file(GLOB functional_test_framework
LIST_DIRECTORIES FALSE
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
functional/test_framework/*.csv
functional/test_framework/*.py
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/functional/test_framework/crypto)
file(GLOB functional_test_framework_crypto
LIST_DIRECTORIES FALSE
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
functional/test_framework/crypto/*.csv
functional/test_framework/crypto/*.py
)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fuzz)
set(files_to_link
${functional}
${functional_data}
${functional_mocks}
${functional_test_framework}
${functional_test_framework_crypto}
fuzz/test_runner.py
)
foreach(f IN LISTS files_to_link)
if(CMAKE_HOST_WIN32)
set(symlink)
else()
set(symlink SYMBOLIC)
endif()
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/${f} ${CMAKE_CURRENT_BINARY_DIR}/${f} COPY_ON_ERROR ${symlink})
endforeach()
endfunction()
create_test_directory_links()