Skip to content

Custom build profile causes godot-cpp to be ALWAYS recompiled and the SCons cache to be completely ignored on each run #2006

Description

@nikoladevelops

Godot version

4.7 stable

godot-cpp version

master (#1d713bd)

System information

Linux CachyOS x86_64, AMD Ryzen 7 8840HS, AMD Radeon 780M Graphics, 16 GB RAM

Issue description

When using a custom build profile where we strip away classes that are not needed (with enabled_classes and disabled_classes), godot-cpp also stops using the SCons cache and instead ALWAYS re-compiles ALL OBJECT FILES. This is wrong and must be fixed. Meanwhile if we don't use a build profile, we always get the correct behavior and SCons cache always works.

Steps to reproduce

  1. Run git clone https://github.com/godotengine/godot-cpp-template.git
  2. Run git submodule update --init --recursive
  3. In the example template, make sure you checkout the LATEST master branch changes of godot-cpp
  • cd godot-cpp
  • git switch master
  • git pull
  1. Go inside the root SConstruct file and ensure the build profile line is commented, so you can see the CORRECT AND WORKING BEHAVIOR FIRST
# localEnv["build_profile"] = "build_profile.json"

Run the following

scons api_version=4.7 --debug=explain

The first time you run this command the output will take A LONG time to compile since a build profile isn't being used and that's totally fine.
However take note of the output:


scons: building `godot-cpp/gen/src/classes/visual_shader_node_constant.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/classes/visual_shader_node_constant.cpp ...
scons: building `godot-cpp/gen/src/classes/plane_mesh.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/classes/plane_mesh.cpp ...
scons: building `godot-cpp/gen/src/classes/light_occluder2d.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/classes/light_occluder2d.cpp ...
scons: building `godot-cpp/gen/src/classes/reg_ex.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/classes/reg_ex.cpp ...
scons: building `godot-cpp/gen/src/classes/csg_combiner3d.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/classes/csg_combiner3d.cpp ...
scons: building `godot-cpp/gen/src/classes/open_xr_haptic_vibration.linux.template_debug.x86_64.o' because it doesn't exist

As you can see on the very first run, these object files DO NOT YET exist, so the output tells us

... because it doesn't exist

Now re-run the command again.

scons api_version=4.7 --debug=explain

Now notice how the CORRECT OUTPUT LOOKS LIKE

❯ scons api_version=4.7 --debug=explain
scons: Reading SConscript files ...
Auto-detected 16 CPU cores available for build parallelism. Using 15 cores by default. You can override it with the -j argument.
Building for architecture x86_64 on platform linux
scons: done reading SConscript files.
scons: Building targets ...
scons: `godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a' is up to date.
scons: `bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' is up to date.
scons: `project/bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' is up to date.
scons: done building targets.

As you can see there is NO MENTION OF THE MESSAGE:

... because it doesn't exist

Because the build system uses the CACHED object files, since there were NO NEW CODE CHANGES anywhere. This is the completely correct and expected behavior.

===============

THE BUG.

Now to redo the test, with a build profile.

First clear all object files

scons -c

Now go in the root SConstruct file and UNCOMMENT this line. THIS IS IMPORTANT.

localEnv["build_profile"] = "build_profile.json"

This will now use the build_profile.json that looks like this:

{
	"_": "This is an example build profile and not used by default. See the SConstruct file for more information.",
	"type": "feature_profile",
	"enabled_classes": ["Node3D", "ImageTexture", "OS"]
}

The goal is to obviously strip away unnecessary classes, so that they don't get compiled and speed up the process a bit. We use enabled_classes OR disabled_classes to achieve it.

Do the first run of the scons command to re-compile

scons api_version=4.7 --debug=explain

You will see all object files being re-created and everything re-compiled. THIS IS CORRECT SINCE IT'S THE VERY FIRST RUN, so we get similar output:


Compiling godot-cpp/gen/src/classes/open_xr_spatial_marker_tracking_capability.cpp ...
scons: building `godot-cpp/gen/src/classes/sprite_base3d.linux.template_debug.x86_64.o' because it doesn't exist
...

We obviously get the message:

... because it doesn't exist

Finally at the end we get

Linking Shared Library bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so ...
scons: building `project/bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' because it doesn't exist
Install file: "bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so" as "project/bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so"
scons: done building targets.

This is the message for a first ever run, the template debug .so file has been created in bin directory.

However what happens when we re-run the scons command to try and compile again?

..

You will notice that the SCons cache is no longer being used and we still get the messages of re-creating the object files..

Example:

Compiling godot-cpp/gen/src/classes/ref_counted.cpp ...
scons: building `godot-cpp/gen/src/variant/packed_int32_array.linux.template_debug.x86_64.o' because it doesn't exist
Compiling godot-cpp/gen/src/variant/packed_int32_array.cpp ...
scons: building `godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a' because it doesn't exist
Linking Static Library godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a ...
Ranlib Library godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a ...
scons: building `bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' because it doesn't exist

So all of these object files get re-created again, as if they didn't exist... even though we created them on the very first run..

Strange thing is that at the end of the output we get this message

Compiling godot-cpp/gen/src/variant/packed_int32_array.cpp ...
scons: `godot-cpp/bin/libgodot-cpp.linux.template_debug.x86_64.a' is up to date.
scons: `bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' is up to date.
scons: `project/bin/linux/libEXTENSION-NAME.linux.template_debug.x86_64.so' is up to date.
scons: done building targets.

The message:

... is up to date.

So the build system KNOWS that the files have not been changed and YET IT STILL RE-COMPILES EVERY OBJECT FILE.

If you try re-compiling again and again, you will notice that the SCons cache is NEVER USED. Those object files always get re-created no matter what.... This shouldn't happen. We should be able to have a custom build profile ALONG WITH SCons cache both speeding up our development.

In conclusion:
The build profile still works in the sense that it eliminates/strips away classes that are not needed for the build processes, but it also introduces a BUG where the SCons cache of the object files is NEVER used.

Previously I had tested the 4.5 branch of godot-cpp, and this bug was NOT present there. This is some new buggy behavior introduced in 10.0.0 of godot-cpp.

Should build profiles still be used or are they in the process of refactoring? Am I missing something?

Just for clarity my system info:

SCons: v4.10.1.055b01f429d58b686701a56df863a817c36bb103, Sun, 16 
Python 3.14.5
git version 2.54.0
godot-cpp: master branch (4.7) latest
OS: Linux CachyOS

Also tested on Windows 10 with SCons 4.9, so I'm pretty sure this is a bug with godot-cpp itself.

Minimal reproduction project

Clone the godot-cpp-template repository like I explained.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions