godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.96k stars 20.18k forks source link

[Building] LINKFLAGS don‘t actually set linker flags #86711

Closed terraquad closed 8 months ago

terraquad commented 8 months ago

Tested versions

In branch 4.2 of the source code

System information

Ubuntu Server 22.04 LTS - scons 4.0.1; clang 14; lld 14

Issue description

When using the LINKFLAGS scons argument, it will error because the argument doesn’t exist on the compiler:

$ scons p=linux linker=lld LINKFLAGS=“--threads“ use_llvm=yes
(…)
clang: error: unsupported option ‘--threads‘; did you mean ‘-mthreads‘?
(…)

How can I explicitly send arguments to lld?

Steps to reproduce

See above

Minimal reproduction project (MRP)

N/A

AThousandShips commented 8 months ago

Can you please list what the actual command is that triggers this error? It does say clang: ... but knowing what the actual invocation was would be important

akien-mga commented 8 months ago

Link flags are passed to the compiler, so you need to use -Wl,--threads.

terraquad commented 8 months ago

This is the build process:

$ GENKEY=1 ./build.sh linux-x86_64 linux-arm64 windows-x86_64
Already up to date.
 Building Godot for linux (x86_64)...
Auto-detected 4 CPU cores available for build parallelism. Using 4 cores by default. You can override it with the -j argument.
Using linker program: lld
clang: error: unsupported option '--threads'; did you mean '-mthreads'?
CalledProcessError: Command '['clang', '-Wl,--version', '--threads', '-fuse-ld=lld', '-flto']' returned non-zero exit status 1.:
  File "/appdata/user/godot-blowback/SConstruct", line 572:
    detect.configure(env)
  File "/appdata/user/godot-blowback/./platform/linuxbsd/detect.py", line 465:
    linker_version_str = subprocess.check_output(
  File "/usr/lib/python3.10/subprocess.py", line 421:
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.10/subprocess.py", line 526:
    raise CalledProcessError(retcode, process.args,

My build.sh file:

#!/bin/bash

function build() {
  scons p=$1 arch=$2 target=template_debug -Q
  scons p=$1 arch=$2 target=template_release -Q
}

git pull
encKey=$(openssl rand -hex 32)
if [ $GENKEY -ne 1 ]; then
  encKey=$(cat build.gdkey)
fi
export SCRIPT_AES256_ENCRYPTION_KEY=$encKey
echo $encKey > build.gdkey
set -e

for target in "$@"; do
  platform=$(echo "$target" | tr "-" "\n" | head -n 1)
  arch=$(echo "$target" | tr "-" "\n" | tail -n 1)
  color_hl=$(printf '\033[30;42;1m')
  color_reset=$(printf '\033[0m')
  echo $color_hl "Building Godot for $platform ($arch)..." $color_reset
  build $platform $arch
done
strip bin/*

echo
echo "Done! Make sure you set the encrypton key in Godot before exporting (build.gdkey)."

My custom.py file:

production = "yes"
use_mingw = "yes"
use_llvm = "yes"
optimize = "speed"
linker = "lld"
LINKFLAGS = "--threads" # Error here

openxr = "no"
minizip = "no"
module_openxr_enabled = "no"
module_mobile_vr_enabled = "no"
module_webxr_enabled = "no"
module_tga_enabled = "no"
module_tinyexr_enabled = "no"

I will inform you if @akien-mga 's version compiles or not.

Also maybe its a difference between building the editor and building the export templates.

terraquad commented 8 months ago

Just tested @akien-mga 's approach, but now it errors like this:

Already up to date.
 Building Godot for linux (x86_64)...
Auto-detected 4 CPU cores available for build parallelism. Using 4 cores by default. You can override it with the -j argument.
Using linker program: lld
ld.lld: error: --threads: expected a positive integer, but got '-lgcc'
ld.lld: error: --thinlto-jobs: invalid job count: -lgcc
clang: error: linker command failed with exit code 1 (use -v to see invocation)
CalledProcessError: Command '['clang', '-Wl,--version', '-Wl,--threads', '-fuse-ld=lld', '-flto']' returned non-zero exit status 1.:
  File "/appdata/user/godot-blowback/SConstruct", line 572:
    detect.configure(env)
  File "/appdata/user/godot-blowback/./platform/linuxbsd/detect.py", line 465:
    linker_version_str = subprocess.check_output(
  File "/usr/lib/python3.10/subprocess.py", line 421:
    return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
  File "/usr/lib/python3.10/subprocess.py", line 526:
    raise CalledProcessError(retcode, process.args,

I only changed LINKFLAGS in custom.py to "-Wl,--threads", everything else is the same (see above) With "-Wl,--threads=4" it works, but I want to use all availbale threads like the compiler (my game source should be portable)

akien-mga commented 8 months ago

The error tells you what the issue is. lld's --threads expects a number of threads as the next argument. This can be reproduced trivially:

$ gcc main.c -fuse-ld=lld -Wl,--threads
ld.lld: error: --threads: expected a positive integer, but got '-lgcc'
ld.lld: error: --thinlto-jobs: invalid job count: -lgcc
collect2: error: ld returned 1 exit status

Looking at the help output:

$ ld.lld --help | grep threads
  --thinlto-jobs=<value>  Number of ThinLTO jobs. Default to --threads=
  --threads=<value>       Number of threads. '1' disables multi-threading. By default all available hardware threads are used

Most likely if you get this error like me, it means your LLD defaults to multithreaded and doesn't support an argument-less --threads anymore.

terraquad commented 8 months ago

But when I start the build process in one SSH session, and use htop in another, I can see that during link process, only one core is at 100%, the others are idling at 0.3%. While compiling, all cores are at 100%, which is the desired behaviour. In lld's help output it says that it has a default option which I want to use. How do I invoke that default option?

akien-mga commented 8 months ago

If the option is a default, you don't have to set it, it's the default behavior :)

But you're setting production=yes, which enables LTO. LLD's (full) LTO doesn't support threads.

Its ThinLTO does (and --thinlto-jobs will infer the value from --threads by default, according to the help output), so you can pass lto=thin if you want, and that might work.

Alternatively, you can link with GNU ld (bfd) which supports multi-threaded LTO out of the box.

terraquad commented 8 months ago

grafik This is htop while linking godot...

I'll look into switching to bfd. Thanks for the suggestion!