Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cmake] Serialize native builds for Make generator #121021

Merged
merged 1 commit into from
Jan 15, 2025

Conversation

arthurqiu
Copy link
Contributor

@arthurqiu arthurqiu commented Dec 24, 2024

The build system is fragile by allowing multiple invocation of subprocess builds in the native folder for Make generator.

For example, during sub-invocation of the native llvm-config, llvm-min-tblgen is also built. If there is another sub-invocation of the native llvm-min-tblgen build running in parallel, they may overwrite each other's build results, and may lead to errors like "Text file busy".

This patch adds a cmake script that uses file lock to serialize all native builds for Make generator.

Copy link
Collaborator

@joker-eph joker-eph left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this fragile? The build system allows multiple invocation of subprocess builds in the native folder.
Isn't there a way to present this?

@arthurqiu
Copy link
Contributor Author

arthurqiu commented Dec 24, 2024

@joker-eph this is indeed fragile. Following previous discussion in https://reviews.llvm.org/D149072, it shouldn't be a problem for Ninja generator because of the use of console tool and for Visual Studio because of the introduction of dependency chain. It mentioned job server for GNU make, but I don't see it's being used anywhere.

I think it's possible to leverage job server to serialize the sub-make invocation. More specifically, below setup is needed if I understand it correctly:
Step 1. create a named pipe
Step 2. generate 1 one-byte token into the pipe
Step 3. pass the named pipe via --jobserver-auth option for the sub-make invocation

Alternatively, shall we simply apply the dependency chain to GNU make generator as well? It's mentioned in https://reviews.llvm.org/D149072 that it would regress Makefile build time. However, I don't feel it would regress much compared with the job server solution.

--
EDIT: After a second thought, I think both mentioned solutions would regress the build time significantly.

@joker-eph
Copy link
Collaborator

I think you should pull in the folks from the review you mentioned.

@llvmbot llvmbot added the cmake Build system in general and CMake in particular label Dec 25, 2024
@arthurqiu
Copy link
Contributor Author

arthurqiu commented Dec 25, 2024

Inspired by https://discourse.cmake.org/t/good-way-of-running-custom-commands-serially/8412, I implemented serial execution of sub-make invocations via cmake file(lock). The alternative is to use flock, but flock is not available on all platforms.

@arthurqiu
Copy link
Contributor Author

@llvm-beanz @aganea @smeenai @mstorsjo @chapuni Please kindly review.

@arthurqiu arthurqiu force-pushed the aq/fix_native_llvm-config branch from b0dc686 to e6c555e Compare December 25, 2024 10:43
@arthurqiu arthurqiu changed the title [cmake] Fix overlapping native llvm-min-tblgen builds [cmake] Serialize native builds for Make generator Dec 25, 2024
@arthurqiu arthurqiu force-pushed the aq/fix_native_llvm-config branch from e6c555e to d3c3711 Compare December 25, 2024 10:55
@arthurqiu arthurqiu requested a review from joker-eph January 2, 2025 01:55
@arthurqiu
Copy link
Contributor Author

Ping

Copy link
Collaborator

@llvm-beanz llvm-beanz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this mostly looks fine. One small suggestion.

llvm/cmake/modules/LLVMExternalProjectUtils.cmake Outdated Show resolved Hide resolved
@arthurqiu arthurqiu force-pushed the aq/fix_native_llvm-config branch from e419a54 to add0b79 Compare January 8, 2025 08:15
@arthurqiu
Copy link
Contributor Author

@joker-eph @llvm-beanz The PR is ready for merge. I don't have commit access to llvm-project repo. Could you please help merge if it looks all good.

@arthurqiu
Copy link
Contributor Author

@joker-eph @llvm-beanz The PR is ready for merge. I don't have commit access to llvm-project repo. Could you please help merge if it looks all good.

Ping. Sorry for bothering.

set(make_cmd "$(MAKE)" "-C" "${bin_dir}" "${target}")
set(file_lock_script "${LLVM_CMAKE_DIR}/FileLock.cmake")
set(${out_var} ${CMAKE_COMMAND} "-DLOCK_FILE_PATH=${stamp_dir}/cmake.lock"
"-DCOMMAND='${make_cmd}'"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might be better off using something like | instead of a semicolon-separated list when constructing make_cmd above; and then replacing | with ; inside FileLock.cmake. Using \; or $<SEMICOLON> (since all places this will be used support generator expressions) would also work. You can then remove the separate_arguments inside FileLock.cmake and have things still work correctly for paths with spaces.

The single quotes here will also likely cause issues on Windows; you can use \" instead so that the command ends up with double quotes instead.

Copy link
Contributor Author

@arthurqiu arthurqiu Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smeenai Thanks for reviewing. I've made changes according to your suggestions. Please take a look.

I found that semicolon-separated list just happened to work because VERBATIM was not used in add_custom_command, even that the build cmd was indeed problematic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick test and it looks like ExternalProject_Add_Step would wrap command with sh -c, i.e. it has the same behavior as add_custom_command without VERBATIM, and unfortunately ExternalProject_Add_Step does not have a VERBATIM argument. So it would break code here if either | or \; is used as separator because they have special meaning in shell.

For now, I use @ as separator. We can choose something different if @ is too common. I'm not familiar with how to test CMake flow here. So I just ran some CMake unit test to verify cmd parsing works as expected with/without VERBATIM mode on both linux/windows.

@arthurqiu arthurqiu force-pushed the aq/fix_native_llvm-config branch from add0b79 to 34023d6 Compare January 14, 2025 07:35
@arthurqiu arthurqiu force-pushed the aq/fix_native_llvm-config branch from 34023d6 to 56be0d9 Compare January 14, 2025 08:32
@arthurqiu arthurqiu requested a review from smeenai January 15, 2025 01:15
Copy link
Collaborator

@smeenai smeenai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. @ seems good to me.

@smeenai smeenai merged commit 6655c53 into llvm:main Jan 15, 2025
8 checks passed
paulhuggett pushed a commit to paulhuggett/llvm-project that referenced this pull request Jan 16, 2025
The build system is fragile by allowing multiple invocation of
subprocess builds in the native folder for Make generator.

For example, during sub-invocation of the native llvm-config,
llvm-min-tblgen is also built. If there is another sub-invocation of the
native llvm-min-tblgen build running in parallel, they may overwrite
each other's build results, and may lead to errors like "Text file
busy".

This patch adds a cmake script that uses file lock to serialize all
native builds for Make generator.
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 16, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64-aix running on aix-ppc64 while building llvm at step 3 "clean-build-dir".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/64/builds/1992

Here is the relevant piece of the build log for the reference
Step 3 (clean-build-dir) failure: Delete failed. (failure) (timed out)
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: ClangScanDeps/verbose.test' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
RUN: at line 1: rm -rf /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
+ rm -rf /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
RUN: at line 2: split-file /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
+ split-file /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp
RUN: at line 3: sed -e "s|DIR|/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp|g" /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json.in > /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json
+ sed -e 's|DIR|/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp|g' /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json.in
RUN: at line 5: /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/clang-scan-deps -compilation-database /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json -v -o /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/result.json 2>&1 | /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/FileCheck /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test
+ /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/clang-scan-deps -compilation-database /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/cdb.json -v -o /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/tools/clang/test/ClangScanDeps/Output/verbose.test.tmp/result.json
+ /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/build/bin/FileCheck /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test
/home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test:6:11: error: CHECK: expected string not found in input
// CHECK: *** Virtual File System Stats:
          ^
<stdin>:1:1: note: scanning from here
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
^
<stdin>:1:8: note: possible intended match here
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
       ^

Input file: <stdin>
Check file: /home/powerllvm/powerllvm_env/aix-ppc64/clang-ppc64-aix/llvm-project/clang/test/ClangScanDeps/verbose.test

-dump-input=help explains the following input dump.

Input was:
<<<<<<
           1: PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. 
check:6'0     X~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: no match found
check:6'1            ?                                                                                                     possible intended match
>>>>>>

--

********************


DKLoehr pushed a commit to DKLoehr/llvm-project that referenced this pull request Jan 17, 2025
The build system is fragile by allowing multiple invocation of
subprocess builds in the native folder for Make generator.

For example, during sub-invocation of the native llvm-config,
llvm-min-tblgen is also built. If there is another sub-invocation of the
native llvm-min-tblgen build running in parallel, they may overwrite
each other's build results, and may lead to errors like "Text file
busy".

This patch adds a cmake script that uses file lock to serialize all
native builds for Make generator.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cmake Build system in general and CMake in particular
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants