-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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
toolchain abstraction #24851
toolchain abstraction #24851
Conversation
This comment has been minimized.
This comment has been minimized.
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.
Looks like a good direction and starting point for simplifying the add of a new toolchain.
The reduction of the number of files needed and the possibility for inheriting the properties, and override/set those properties need and supported, reduces and simplifies the steps needed to add a new toolchain.
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.
Very nice, only a few nit picks.
Properties appear the way to go, as a real "data structure" rather than order-dependent variable expansion.
I like that the skeletal templates also serves nicely as a central point of Documentation.
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.
Some initial observations.
CMakeLists.txt
Outdated
endif() | ||
|
||
# @Intent: Set compiler specific macro inclusion of AUTOCONF_H | ||
toolchain_cc_imacros(${AUTOCONF_H}) | ||
zephyr_compile_options($<TARGET_PROPERTY:compiler,imacros>${AUTOCONF_H}) |
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.
Need the ability to add a space, in our case, or some other assignment character between the imacros property and the string result from ${AUTOCONF_H}.
Setting the imacros property as follows, seems to work in our case, but the resulting option gets enclosed in " which is probably not desirable.
set_compiler_property(PROPERTY imacros "-imacros ")
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.
thanks for letting me know.
This is exactly why it's still a draft, in order to collect all the knowledge needed to make this abstraction as useful as possible.
Will try to include in next update round.
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 agreed at the last Zephyr Toolchain Working Group meeting on May 14th, I have looked into our Toolchain/compiler support for having a single -imacros include file. This file should then #include both the autoconf.h and the zephyr_stdint.h files, thus needing only one -imacros compiler option and header.
The test was performed with the current macro/function based toolchain abstraction, and thus not with the property based toolchain abstraction from this PR, but that makes no difference in this case.
The toolchain_cc_imacros was modified to look as follows:
macro(toolchain_cc_imacros header_file)
# Generate the common imacros include file, together with a verification header
# which simply produces a warning every time the file is included...
if(NOT ${header_file} MATCHES "/zephyr_.*\.h") \
file(WRITE /tmp/z_imacros_verf.h "#warning \"-imacros include z_imacros_verf.h\"\n")
file(WRITE /tmp/z_imacros.h "/* Auto generated, do not edit */\n\n"
"#include </tmp/z_imacros_verf.h>\n")
# Add the -imacros option to the compiler flags
zephyr_compile_options(-imacros /tmp/z_imacros.h)
endif()
# Append the #include of the given header file
file(APPEND /tmp/z_imacros.h "#include <${header_file}>\n")
endmacro()
The above results in a generated /tmp/z_imacros.h which #include autoconf.h and zephyr_stdint.h.
For our compiler, this works fine, it spits out the warning for the z_imacros_verf.h together with including the information needed from the autoconf.h and zephyr_stdint.h header files.
If other compilers supports this as well, it could be that a common imacros header should be generated, similar to above macro, but just more generic. If it turns out that not all compilers support the #include in the -imacros include file, then perhaps there should exist a way a given toolchain could have such a header file generated and added as compile option, similar to the flexibility of the toolchain_cc_imacros macro.
On a side note, I actually discovered that the reason our compiler does not accept -imacros inclusion of the two header files, is not that it does not accept two -imacros options, but rather that the zephyr_compile_options, hence target_compile_options, strips one of the -imacros options leaving only one -imacros option with two header files separated by spaces, and that the compiler does not like. The zephyr_compile_options strips the last -imacros option, as it sees it as a duplicate, since we have to have a space between the -imacros and the header file.
Adding the two -imacros options as zephyr_compile_options("-include ${header_file}")
actually works for our compiler, but it adds " around each -imacros option.
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.
Need the ability to add a space, in our case, or some other assignment character between the imacros property and the string result from ${AUTOCONF_H}.
Is this a compiler-specific requirement? Just making sure.
the reason our compiler does not accept -imacros inclusion of the two header files, is not that it does not accept two -imacros options, but rather that the zephyr_compile_options, hence target_compile_options, strips one of the -imacros options leaving only one -imacros option with two header files separated by spaces,
I understood CMake performs flag deduplication, correct? I mean not related and not specific to Zephyr. Not specific to -imacros
either.
That's why there's no space, as a workaround: #7216 (comment)
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.
Is this a compiler-specific requirement? Just making sure.
Yes, it is a compiler specific requirement. In our case, the compiler only accepts a space between the option and the header file name, nothing else.
I understood CMake performs flag deduplication, correct? I mean not related and not specific to Zephyr. Not specific to -imacros either.
That is true, CMake performs flag deduplication on any duplicated flags, not specific to -imacros, nor to Zephyr. Perhaps @tejlmand could confirm that?
That's why there's no space, as a workaround: #7216 (comment)
Yes, but as stated previously, not all compilers support the 'no space' workaround. Which is why we need a way to circumvent the CMake flag deduplication, and also handle those cases where the compiler only supports one -imacros option.
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.
Is this a compiler-specific requirement? Just making sure.
Yes, it is a compiler specific requirement. In our case, the compiler only accepts a space between the option and the header file name, nothing else.
I understood CMake performs flag deduplication, correct? I mean not related and not specific to Zephyr. Not specific to -imacros either.
That is true, CMake performs flag deduplication on any duplicated flags, not specific to -imacros, nor to Zephyr. Perhaps @tejlmand could confirm that?
Well, that was true for older CMake versions, but since CMake v3.12, you can avoid the deduplication:
While beneficial for individual options, the de-duplication step can break up option groups. For example, -D A -D B becomes -D A B. One may specify a group of options using shell-like quoting along with a SHELL: prefix. The SHELL: prefix is dropped and the rest of the option string is parsed using the separate_arguments() UNIX_COMMAND mode. For example, "SHELL:-D A" "SHELL:-D B" becomes -D A -D B.
https://cmake.org/cmake/help/v3.12/command/target_compile_options.html
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.
finally had time to try it out in this PR, and here is the result when compiling main.c
:
/opt/zephyr-sdk-0.11.3/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc
-DBUILD_VERSION=zephyr-v2.3.0-969-g2811e4ecdde1
-DKERNEL
-DNRF52840_XXAA
-D_FORTIFY_SOURCE=2
-D__PROGRAM_START
-D__ZEPHYR__=1
...
-isystem /projects/github/ncs/zephyr/lib/libc/minimal/include
-isystem /opt/zephyr-sdk-0.11.3/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/9.2.0/include
-isystem /opt/zephyr-sdk-0.11.3/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/9.2.0/include-fixed
-Os
-imacros /projects/github/ncs/zephyr/samples/hello_world/build/zephyr/include/generated/autoconf.h
-ffreestanding
-fno-common
-g
-mcpu=cortex-m4
-mthumb
-mabi=aapcs
-imacros /projects/github/ncs/zephyr/include/toolchain/zephyr_stdint.h
...
-o CMakeFiles/app.dir/src/main.c.obj
-c ../src/main.c
and as it can be seen, there is not deduplications of -imacro
.
And there is even a space
between the -imacro
and the header file.
@daor-oti Going to push an update soon, so that it can be tested with custom compilers.
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.
@daor-oti feel free to try the updated version with your custom compiler.
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.
@tejlmand Thank you, this looks good and is working perfectly with our compiler, hence no deduplication of -imacros. Also the, in our case, needed space is there without us having to explicitly add the space to the imacros property, nice.
CMakeLists.txt
Outdated
|
||
# @Intent: Enforce standard integer type correspondance to match Zephyr usage. | ||
# (must be after compiler specific flags) | ||
toolchain_cc_imacros(${ZEPHYR_BASE}/include/toolchain/zephyr_stdint.h) | ||
zephyr_compile_options($<TARGET_PROPERTY:compiler,imacros>${ZEPHYR_BASE}/include/toolchain/zephyr_stdint.h) |
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 our tool chain do not support, and others may not support, more than one -imacros option, some method of excluding this second addition will be needed. Also, our tool chain does not support having more than one header file defined in one -imacros option.
The old toolchain_cc_imacros macro allowed for picking which imacros header to add and skip others, the new property based system does not.
Question is whether having one 'generated' header which then include autoconf.h and zephyr_stdint.h would work for all tool chains, not even sure about ours, but that could be investigated as a possible solution.
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, there certainly need to be a way to handle this in a nice way.
And your toolchain is not the only one which only support one imacro
.
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.
Please see above comment on imacros include.
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.
Please give feedback on the update PR.
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.
For our compiler the above deduplication has resolved this issue, but still, there are compilers which can only take on -imacros option, so a method for handling that will still be needed.
zephyr_compile_options( | ||
$<$<COMPILE_LANGUAGE:C>:${CC_CSTD}> | ||
$<$<COMPILE_LANGUAGE:C>:$<TARGET_PROPERTY:compiler,cstd>${CSTD}> |
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.
For compilers that do not support -std and hence the default c99, the global property CSTD can simply be set to empty string as the following:
set_property(GLOBAL PROPERTY CSTD " ")
and the cstd can then be left to use the template setting.
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 assume this is acceptable ?
Current Zephyr would require you to do:
set_property(GLOBAL PROPERTY CSTD " ")
right ?
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.
This is perfectly acceptable.
I only mentioned it as a hint that it might be needed by some compilers and that it was easily achievable by simply setting the global property to an empty string.
@TTornblom FYI |
nice to have a template. that will be a good start point to support new toolchains |
The Xtense xcc compiler now uses the new compiler abstraction. Signed-off-by: Torsten Rasmussen <[email protected]>
This commit fixes an issue in the process_flags function. The function check a list of flags for generator expression for provided language, for example: $<$<COMPILE_LANGUAGE:C>:--flag> and then converts that into a single compile flag, `--flag` This works as long as $<COMPILE_LANGUAGE:[language]> is the only generator expression present in the flag. In case the flag contains multiple generator expression, then the current substitution fails. This commit keep existing behaviour for simple cases, but extends the more complex cases into a always enabled generator expression, that is $<$<COMPILE_LANGUAGE:C>:$<ADDITIONAL_EXPRESSION>> into $<1:$<ADDITIONAL_EXPRESSION>> and $<$<FIRST_EXPRESSION>$<COMPILE_LANGUAGE:C>:--flag> into $<$<FIRST_EXPRESSION>$<1:--flag> Signed-off-by: Torsten Rasmussen <[email protected]>
When fetching include, system include, compiler options, or compiler defines, then it is important to strip the SHELL: (no de-duplication) tag of any flag. Signed-off-by: Torsten Rasmussen <[email protected]>
This commit updates the get Zephyr settings functions to be able to handle settings if those settings are expressed using a generator expression. As example, zephyr_get_include_directories_for_lang(...) would prefix each include property of zephyr_interface with `-I`, like this: Property: include;include/generated;lib/libc/minimal/include becomes: `-Iinclude -Iinclude/generated -Ilib/libc/minimal/include` But if the property contains a generator expression: Property: include;$<TARGET_PROPERTY:compiler,some_include> becomes: -Iinclude -I$<TARGET_PROPERTY:compiler,some_include> and in case that property is a list, this results in: `-Iinclude -Iinclude/list_item1;include/list_item2;include/list_itemN` and thus breaking the build. This is fixed by using `$<JOIN:<list>>` expression instead, which ensures all list item, regardless of provided as simple list or through the usage another generator expression, will always expand correctly. Functions updated in the commit: - zephyr_get_include_directories_for_lang - zephyr_get_system_include_directories_for_lang - zephyr_get_compile_definitions_for_lang - zephyr_get_compile_options_for_lang The sample `application_development/external_lib` has been updated according to those changes. Signed-off-by: Torsten Rasmussen <[email protected]>
This commit is to be squashed into compiler abstraction commit. Signed-off-by: Torsten Rasmussen <[email protected]>
This command add support for `<command>_flag_final` to all bintools commands. This allows users that has special use-cases to use a CMake script for bintool command execution, and thereby have full control of command invocation and argument processing. Example of how to specify the property for such use: Calling a custom script for elfconvert command: set_property(TARGET bintools PROPERTY elfconvert_command ${CMAKE_COMMAND}) set_property(TARGET bintools PROPERTY elfconvert_flag "") set_property(TARGET bintools PROPERTY elfconvert_flag_final -P elfconvert.cmake) set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-DSTRIP_ALL=True") set_property(TARGET bintools PROPERTY elfconvert_flag_infile "-DINFILE=") set_property(TARGET bintools PROPERTY elfconvert_flag_outfile "-DOUT_FILE=") Signed-off-by: Torsten Rasmussen <[email protected]>
b921627
to
2f2394d
Compare
@tejlmand: "cmake: toolchain disable -imacro deduplication" commit from this PR (merged as f109e68) broke "make zephyr_generated_headers" target, specifically creation of Makefile.exports.* (e.g. Makefile.exports.C) files containing CFLAGS, etc. for integration with external build systems. The effect of that can be seen e.g. at https://ci.linaro.org/job/lite-aeolus-micropython/PLATFORM=frdm_k64f,ZEPHYR_TOOLCHAIN_VARIANT=zephyr,label=docker-xenial-amd64-13/1317/console :
I.e., these I see that there was a similar problem elsewhere, addressed in 9d501f4. I'll try to adapt it to "make zephyr_generated_headers", but not sure if I'll be able to, and may need some help. |
@pfalcon The Already looking at a fix, so you don't need to spend time on that. |
Thanks, appreciate that! |
@pfalcon Could you file a medium issue, a brief description is enough, and assign directly to me. |
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos/zephyr#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: #24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos/zephyr#24851 (cherry picked from commit 2c1f079) Original-Signed-off-by: Torsten Rasmussen <[email protected]> GitOrigin-RevId: 2c1f079 Change-Id: Id7caa73314281448818c69bf862069ae4466e1e4 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/4800587 Commit-Queue: Fabio Baltieri <[email protected]> Tested-by: Fabio Baltieri <[email protected]> Reviewed-by: Fabio Baltieri <[email protected]> Tested-by: ChromeOS Prod (Robot) <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos/zephyr#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
Remove commented out code which are no longer needed. Code was made obsolete here and should have been removed at the time: zephyrproject-rtos#24851 Signed-off-by: Torsten Rasmussen <[email protected]>
The main purpose of this proposal is to minimize the work needed when implementing support for an additional toolchain.
Currently, when implementing support for a new toolchain in Zephyr or when
implementing downstream support for a custom / vendor specific toolchain
there are several macros to be defined, even if the are empty.
The macro based approach also offers challenges as well as additional
maintenance burden when new macros are introduced, as all downstream users with
custom toolchains must implement those (even if empty).
Furthermore, it also requires additional split of code into cmake files that
simple implements a single macro, in order to allow a toolchain to source
only a subset. (as example:
target_base.cmake
,target_freestanding.cmake
,target_barmetal.cmake
)This is due to the fact that macros cannot be overwritten, once they are defined.
(In fact CMake allows for this, but let's avoid that path, as it leads to other
risks and complications).
Now, separating parts into dedicated cmake files might always be a good idea, seen from design perspective, but it should be done because it makes sense, and not just splitting because of macro reuse / lack of reusability.
This draft instead propose the use of dedicated targets and properties on those
targets.
The benefits are:
Possibility of defining a default flag (can be cleared / overwritten later)
(currently default is no flag)
Possibility of inheriting a set of flags from other compiler / linker and
overwrite only parts that differs. For example clang can inherit all of gcc
compiler flag and only overload warnings and coverage, and clear
security_fortify and hosted flags. See
cmake/compiler/clang/compiler_flags.cmake
.https://github.com/tejlmand/zephyr/blob/prototyping/16031_toolchain_abstraction/cmake/compiler/clang/compiler_flags.cmake
More uniform set and use design
Ability to manually overwrite a flag AFTER it has been used on a compile target.
For example in app CMakeLists.txt and
find_package(Zephyr)
Clearer separation:
compiler/<compiler-name>/compiler_flags.cmake
linker/<linker-name>/linker_flags.cmake
bintools/<bintools-name>
cmake files.A couple of comments related to approach chosen to questions that might arise:
Why not use normal variables instead of target properties ?
It would be possible to achieves almost similar behavior with variables, but
not completely.
But the split into a target with property ensures:
For example, if you do:
We ensure a more common usage principle.
Current solution has a couple of different ways for the macros,
x_flag vs x_flags as well as parameter handling:
macro(toolchain_cc_warning_base)
- Sets flags directly as compile optionsmacro(toolchain_cc_optimize_for_debug_flag dest_var_name)
- Sets the compile flag ondest_var_name
, unless already set.macro(toolchain_cc_cpp_base_flags dest_list_name)
- Appends the compile flagdest_var_name
, keeping any existing values on the list.Some macros base the behavior on the parameter.
Some macros set linker options in the compiler macros:
bintools macros sometimes set linker flags: