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
Normalized C++ compilation options for single-threaded targets #10143
Conversation
lib/std/build/RunStep.zig
Outdated
@@ -136,6 +137,23 @@ pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void { | |||
self.stderr_action = .{ .expect_exact = self.builder.dupe(bytes) }; | |||
} | |||
|
|||
/// Returns true if the step could be run, otherwise false | |||
pub fn isRunnable( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might have missed that, but why is this logic duplicated from cross_target.zig
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not quite sure what exactly is duplicated here as CrossTarget declares the executors to use, and this code is just using those. In particular this helper function could be used in the RunStep to check if the step is viable (going to work) to avoid runtime errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh sorry, what I meant to point out is that we already have the ability to run (cross-target) tests that require an emulator or similar, therefore I don't really see the need for this in RunStep.zig
. See for instance output of zig test --help
:
...
Test Options:
--test-filter [text] Skip tests that do not match filter
--test-name-prefix [text] Add prefix to all tests
--test-cmd [arg] Specify test execution command one arg at a time
--test-cmd-bin Appends test binary path to test cmd args
--test-evented-io Runs the test in evented I/O mode
--test-no-exec Compiles test binary without running it
...
We already have a way of specifying a custom execution command which is exactly how we invoke foreign tests on some host for instace, like Wasm in Wasmtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but as I mentioned in the comment, the current RunStep behavior is inconsistent. I guess if it would be called NativeRunStep then it will be less confusing, but right now, then one specifies that it's possible to use QEMU, but RunStep gives IncorrectExe error, it's not immediately obvious that RunStep works with native target only.
Moreover, sometimes it's required to run the exe (not tests) in the emulator. Few use-cases for myself are:
- complicated build processes (like LuaJIT compilation I've mentioned in the PR comment).
buildvm
(compiled from the source code using Zig in my toolchain) that is used for building LuaJIT VM doesn't support cross-compilation, and it's required to be invoked with the target architecture (i.e. to produce 32-bit LuaJIT, I have to use 32-bitbuildvm
). It can't be run as a test as it's standalone program and doesn't export anything to be linked into tests. Please take a look to build.zig for the reference. - cross-platform benchmarks. I'm working with the embedded systems, and need to measure the libraries footprint (e.g. pcre vs hyperscan for regexes). The benchmarks are compiled into executables for the deployment on the target platforms, and it's handy to run them first with QEMU to verify file sizes and memory consumption. While I could definitely use shell scripting for that, using extended RunStep functionality provided in this PR, makes the task much easier.
However, as I said, it's not critical as I have the workaround (like ExecutorRunStep
in the referenced sources above). If you still have doubts, I can just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah gotcha. Hmm, ok, I'll need to have @andrewrk take another look at this as we might already have a way to do this that I'm not aware of.
lib/std/build/RunStep.zig
Outdated
@@ -148,6 +166,42 @@ fn stdIoActionToBehavior(action: StdIoAction) std.ChildProcess.StdIo { | |||
}; | |||
} | |||
|
|||
fn getExternalExecutor(artifact: *LibExeObjStep) !?[]const u8 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, like in the comment above, why do we need to duplicate getExternalExecutor
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't duplicate the code but the name. I guess I can rename it to avoid confusion. This function utilizes CrossTarget's getExternalExecutor()
, but besides that have a check if the executor is enabled. It's similar to the logic for tests.
Just an FYI that C++ exceptions require additional functionality in the zld linker to work on macOS. It's on my roadmap but didn't have time to add that in yet. |
Yes, I've noticed that you UPDATE: Looks like
|
58ed467
to
58fd5ae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for these changes, @nuald. I think we can definitely get this to a mergeable point, and it will be a nice improvement. I have a couple of requests which involve moving logic from the build system to src/Compilation.zig
.
But also I want to make some build system improvements prior to merging this. I hope you don't mind if I go ahead and work on those, and then ask you to rebase this.
Previously there was only `--single-threaded`. This flag now matches other boolean flags, instead of only being able to opt in to single-threaded builds, you can now force multi-threaded builds. Currently this only has the possibility to emit an error message, but it is a better user experience to understand why one cannot choose to enable threads in some cases. This is breaking change to the CLI. Related: #10143
58fd5ae
to
44037f8
Compare
test/standalone/c_compiler/build.zig
Outdated
// macos C++ exceptions could be compiled, but not being catched, | ||
// additional support is required, possibly unwind + DWARF CFI | ||
if (target.getCpuArch().isWasm() or os_tag == .macos) { | ||
exe_cpp.defineCMacro("_LIBCPP_NO_EXCEPTIONS", null); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's going on here? this define logic belongs in the compiler, not in this build.zig file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you know, C++ standard library (use older STL acronym later) heavily uses exceptions, and I've updated the test to use them (as it could be a key functionality for C++ applications like in my use-case). Unfortunately, wasm and macOS (currently) has one issue that I'm not quite sure how to overcome: the code is compiled, but doesn't work correctly. I guess the proper solution would be to stop compiling the code if compiler detects that exceptions are used for wasm and macOS, but it means that C++ STL won't be compiled at all on those platforms, and that would be quite breaking change (as STL still could be used with incorrectly working exceptions if used carefully). I didn't want to risk introducing it as it could affect way too many users.
So, for now I've just declared a macro (it could have any name though) that disables exception code in the test. I was going to fix macOS exception handling later if you team won't have time for that, but for now I've just inserted that stub.
Alright I did the aforementioned prerequisite changes in 1cac99c. If you don't mind, can you rework your changes against latest master and let's go from there? |
44037f8
to
b38cb84
Compare
@andrewrk Could you please re-review the changes? |
Sorry for the delay, I have this in my high priority list for next week. |
… libcxx. Fixed single-threaded mode for Windows.
b38cb84
to
6c4ed42
Compare
* back out the changes to RunStep * move the disabled test to the .cpp code and avoid a confusing name-collision with the _LIBCPP macro prefix * fix merge conflict with the edits to the same test that ensure global initializers are called. Now this branch is only concerned with single-threaded targets and passing the correct macro defines to libc++.
6c4ed42
to
4541509
Compare
The PR contains two major changes:
The reason for (1) is that the current functionality is a little bit confusing as C++ standard library is compiled with the threading support even if an artifact is explicitly flagged to use the single-threaded mode. I've discovered that during dealing with #6573. The original LLVM commit referenced there is being abandoned, and the only way to use C++ for ARM in Zig is using modified standard library, hence this PR.
There are few reason for (2), but none of them are critical, therefore the change could be dropped:
.enable_qemu
and similar flags could be applied to the executable, but the corresponding RunStep if invoked would give theIncorrectExe
error. It's not immediately obvious that the RunStep is applicable for native targets only, and.enable_qemu
is no-op for executables, but for tests only. In theory, those flags should be applied to tests and run steps only, but it's out of scope of this PR.c_compiler
modified in this PR. It's handy to have this ability out-of-box.buildvm
should be invoked on the target platform (please see Cross-compiling 32 bit LuaJIT on a 64 bit host LuaJIT/LuaJIT#664 for the reference). I could successfully compile and use LuaJIT on ARM, but need to use the external executor forbuildvm
. The first commit usesExecutorRunStep
that is partially taken from the project.Testing done by:
zig build test
c_compiler
test with 3 targets (x86_64 Linux host, arm-linux-musleabi, wasm32-wasi):Additional notes:
-fno-exceptions
flag is applied to C++ standard library only, not the final executables. If could be addressed in this or another PR if you want;_LIBCPP_HAS_NO_THREADS
is added forbuildLibCXXABI
for single-threaded targets too as it uses C++ standard library;test.c/test.cpp
code have mixed spaces/tabs, I've restyled the code for the consistency;