There is a bug in 20.03 with the order in which the sub-targets of a virtual target are built.
When you change the order of targets in a project's Properties window (using 'Re-order' button), Code::Blocks does not correspondingly change the order those targets within a virtual target are built. Worse still, when looking at the list of sub-targets for the virtual target, they are shown in the correct order, but this does not reflect the actual build order.
To put it another way: when targets are re-ordered, the order those targets are listed in the targets
attribute of the VirtualTargets
->Add
element of the project file XML is not changed. It appears C::B relies only on this ordering in the XML when building virtual targets, and nothing else (i.e. not the order targets are listed in the project in general).
This causes problems particularly when one sub-target depends on the output of another sub-target within the virtual target - i.e the ordering is critical to successful building. And it is particularly egregious because the user interface in this situation misleads and does not show anything wrong.
To reproduce:
A workaround is to un-tick all the sub-targets from the virtual target (C::B will warn that it may not be empty), then re-tick, followed by re-saving the project.
Please read the following and let us know if this fixes your issue or not:
https://wiki.codeblocks.org/index.php/Common_problems_and_solutions#Multi-targets_library_and_executable_ignore_interdependence
If the dependency changes from the wiki do not work with C::B 20.03 then please try the latest nightly and let us know if the nightly fixes the issue or not with the dependency changes from the wiki.
If you end up with the problem still not working can you please supply a small project that shows the issue so it can be reproduced using the sample files you supply.
I was already using exactly such a build dependency. That's how I discovered this problem - the main executable target was being built before a library dependency target, even though the target ordering was set for the executable to be built last.
I have attached a sample project showing how, after the targets have been re-ordered, the virtual target order hasn't changed within the .cbp file. Note how the order is 'Release', 'Debug', but the order in the virtual target has not changed to match.
Can't put multiple attachments per message, so here also is a screenshot illustrating the disparity between the displayed order of sub-targets in the virtual target, and the actual order in the .cbp file.
Zip the files and attach the zip file.
Did you test with the nightly release? If you did what version did you use?
The foo.cbp project is not complete in that it does not have nay files (no main.cpp, test.cpp etc) . The sample can be a hello world using a library or anything so long as it shows your issue.
It also has no dependencies in it, so unless you are using a workspace with multiple project files you have not setup any dependencies. This is one of the reasons I would like a sample project to see if the dependencies are setup correctly.
Last edit: Andrew Cottrell 2022-10-09
Yes, the bug is present in the latest nightly build, version svn-r12969. I just tried it.
The bug is very simple, and can be plainly seen by just looking at the XML of the .cbp file, but if I must provide a complete project... Please see the attached zip file. You will need the SDCC compiler installed, as I only use C::B with that.
For reference, the following was my build log output. Note that 'Main' gets built before 'Lib', despite the fact 'Lib' should have been first.
```
-------------- Clean: Main in Foo (compiler: Small Device C Compiler)---------------
Cleaned "Foo - Main"
-------------- Clean: Lib in Foo (compiler: Small Device C Compiler)---------------
Cleaned "Foo - Lib"
-------------- Build: Main in Foo (compiler: Small Device C Compiler)---------------
sdcc.exe --debug -I"C:\Program Files\sdcc\include" -c main.c -o obj\Main\main.rel
sdcc.exe -L"C:\Program Files\sdcc\lib" -o bin\Main\foo.hex --debug bin\Lib\lib.lib obj\Main\main.rel
?ASlink-Warning-Couldn't find library 'bin\Lib\lib.lib'
Output file is bin\Main\foo.hex with size 366.00 bytes
-------------- Build: Lib in Foo (compiler: Small Device C Compiler)---------------
sdcc.exe -I"C:\Program Files\sdcc\include" -c lib.c -o obj\Lib\lib.rel
sdar.exe -r bin\Lib\lib.lib obj\Lib\lib.rel
sdar.exe: creating bin\Lib\lib.lib
Output file is bin\Lib\lib.lib with size 1.17 KB
Process terminated with status 0 (0 minute(s), 0 second(s))
0 error(s), 1 warning(s) (0 minute(s), 0 second(s))
```
As I said before, this is all because C::B does not re-order the sub-targets within a virtual target when the main order of those targets is changed, despite the UI giving the misleading impression of having done so.
As per the wiki you need to use a workspace and have multiple projects where you setup dependencies based on the project.
The project/projects can have virtual targets. Attached is the sample reworked to have one workspace and two projects with the dependency configured as per the wiki.
If you want to have dependencies within the one project based on other project target(s) within the one project file then this is an enhancement and not a bug as C::B does not support this at this point in time and as far as I am aware no one is working on this or have any plans to do this (I could be wrong, but the change is low).
Let me ask a question: why does Code::Blocks feature the ability to change the order of targets, if not to have the ability to have certain targets built before or after others?
Please, forget about dependencies for a minute. That is incidental to the matter.
Imagine I have a project with multiple targets where they need to be built in a certain order, but not because the output files of some are dependencies of others. For other reasons, whatever they may be.
Now imagine I create a virtual target containing all those targets so they can all be built in one go. Then I go and re-order some of the targets. But - surprise! C::B doesn't actually build them in the new order! The previous order is still used. However, the order shown in the virtual target editing window is showing as correct!?!
This is a problem concerning the user being able to express a preference (target ordering), but C::B not actually implementing that preference in one area (virtual target build order), and misleading the user in the UI by showing that those preferences are supposedly obeyed (virtual target edit window falsely shows correct order).
If you have a target that needs to be built before another target then you have a dependency. If the targets can be built in any order then there is no dependency.
You can always have a look at the C::B source and supply a patch to resolve what you want.
If you want C::B virtual targets to build in a specific order then this is an enhancement and not a bug as C::B does not support this at this point in time and as far as I am aware no one is working on this or have any plans to do this (I could be wrong, but the change is low).
I have been doing some digging in the C::B code, and the results are illuminating.
If you look in src/sdk/cbproject.cpp, you will see within the ReOrderTargets method there is code in there to sort the targets within a virtual target according to the newly-re-ordered real targets. So C::B is supposed to be maintaining the correct order of real targets within virtual targets.
I can only conclude that this sorting code is not working properly, or its changes are not being persisted to cbProject::m_VirtualTargets. Because when a project is saved (via ProjectLoader::ExportTargetAsProject) or built (via whatever methods in CompilerGCC), there are calls to cbProject::GetVirtualBuildTargetGroup or cbProject::GetExpandedVirtualBuildTargetGroup, which appear to simply return an array of target names in a wxArrayString and don't actually do anything concerning ordering - they just produce stuff in whatever the order already is in m_VirtualTargets.
So, your statement of "C::B does not support this at this point in time" is a load of BS, because the code is already there to do this - it just doesn't work properly for whatever reason, i.e. is buggy.