Skip to content

Support TI Code Generation Tools #10182

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

Closed
yashi opened this issue Sep 24, 2018 · 27 comments
Closed

Support TI Code Generation Tools #10182

yashi opened this issue Sep 24, 2018 · 27 comments
Assignees
Labels
area: Toolchains Toolchains Feature Request A request for a new feature

Comments

@yashi
Copy link
Collaborator

yashi commented Sep 24, 2018

Currently Zephyr doesn't support TI's CGT (Code Generation Tools). TI's CCS (Code Composer Studio) uses CGT as the compiler.

I'd like to support it. To do that, I've discussed with @SebastianBoe (sebo) on IRC channel how we should support non-GCC compilers. sebo suggested to create a compiler wrapper or a compiler driver as he called.

Hi @SebastianBoe ,

As we talked on the irc channel, I've coded up a preliminary version of compiler driver (aka. compiler option translator). Before digging down deep, would you mind to review whether I'm going the right direction or not?

Thanks,

compiler-driver-cgt.py.gz
or
https://gist.github.com/yashi/f3fbf2fc2062486f60211296324c5f2b

@SebastianBoe
Copy link
Collaborator

Hi, I was not able to follow all of the code, but this looks like an approach we can work with.

@SebastianBoe SebastianBoe added area: Toolchains Toolchains Feature Request A request for a new feature labels Sep 24, 2018
@yashi
Copy link
Collaborator Author

yashi commented Sep 25, 2018

Thanks @SebastianBoe . I take it as a go for the current direction. I'll re-submit when I completed the work.

@mped-oticon
Copy link
Collaborator

@SebastianBoe I think it would be cleaner and simpler to handle this within Cmake: Whenever a literal GCC-specific compiler flag is used, abstract it away into a cmake macro (or function). E.g. "-g" becomes something like get_cc_debug_flags() which becomes an API each toolchain has to implement.

@yashi So you translate the command line flags, but do you expect to also modify the C files in-place? For linker specifics as you mentioned on the mailing list?

@SebastianBoe
Copy link
Collaborator

I disagree. Users will be more familiar with GCC flags than our CMake compiler flag API and will therefore find it easier to read and write build scripts with the solution proposed here.

@SebastianBoe
Copy link
Collaborator

Note that we do employ the "wrapper CMake API" approach for some flags, such as -g. This has been wrapped with the CMake variable OPTIMIZE_FOR_DEBUG_FLAG.

But this approach does not work well for the full GCC CLI.

@yashi
Copy link
Collaborator Author

yashi commented Oct 3, 2018

@mped-oticon I haven't encountered any C file to modify. I've posted my diff here. https://gist.github.com/yashi/d200601d68cd3d9948600d99aee5ef1f

There are many debug / test code in it or missing files but hope you feel what I'm doing.

@yashi
Copy link
Collaborator Author

yashi commented Oct 3, 2018

Having compiler option translator / compiler driver is to add yet another layer to our already complex build system, IMO. With cmake, however, it is easier to add arbitrary compile options in sub-directories and we already have some of them. Having if-gcc-elif in all of those cmake is burden to developers who don't know all compilers we will support.

The current compiler driver is designed to be executed at actual compile time but is it possible / good idea to translate compiler option at cmake time? If it can be done DCMAKE_VERBOSE_MAKEFILE=on can be used to debug compiler options.

@SebastianBoe
Copy link
Collaborator

The current compiler driver is designed to be executed at actual compile time but is it possible / good idea to translate compiler option at cmake time?

This is not possible because the compiler options are not known until after "cmake time" (Configure-time). For instance, if generator expression are used;

zephyr_compile_options($<$BOOL:${ENABLE_SOME_FLAG}:--some-flag>)

@yashi
Copy link
Collaborator Author

yashi commented Oct 4, 2018

One more thing. include/misc/rb.h requires alloca.h. But alloca isn't in standard and CGT doesn't support it. #9892 might address this issue, though.

@fnde-ot
Copy link
Collaborator

fnde-ot commented Oct 4, 2018

How about moving all the "zephyr_compile_options" and friends (ld_options, ...) from the root CMakeLists.txt to the specific toolchain cmake files?

Those are included after kconfig so they should have access to CONFIG_* variables as well as most cmake variables. It shouldn't be rocket science to move the logic from the root CMakeLists.txt to -for example- gcc.cmake and others. That would also simplify the root CMakeLists.txt.

As for the few additional flags defined in specific elsewhere in arch or soc, they can stay there and use the ZEPHYR_TOOLCHAIN_VARIANT variable to select appropriate flags if they can be built with more than one toolchain.

@SebastianBoe
Copy link
Collaborator

SebastianBoe commented Oct 8, 2018

How about moving all the "zephyr_compile_options" and friends (ld_options, ...) from the root CMakeLists.txt to the specific toolchain cmake files?

This wouldn't scale. Subsystem-specific information would pollute (what should be subsystem-independent) toolchain portability files.

The condition for when a zephyr_[library_]compiler_options() invocation occurs can be arbitrarily complex, for instance for subsys/bluetooth/controller/CMakeLists.txt:63 it would be when (CONFIG_BT && CONFIG_BT_CTLR && CONFIG_BT_LL_SW && CONFIG_BT_CTLR_FAST_ENC).

Copying this dependency from a subsystem (where it belongs) to a portability file (where it is out-of-place) would cause maintainability issues.

In the proposed solution, portability issues are dealt with by portability scripts, and subsystems are portable across non-gcc toolchains without being aware of any portability layer. This is the solution that separates portability issues and specific subsystems the best and will be the easiest to maintain.

@mped-oticon
Copy link
Collaborator

This wouldn't scale. Subsystem-specific information would pollute (what should be subsystem-independent) toolchain portability files.

That is why the intent should be expressed as a cmake macro/function. That takes care of the general case. If a subsystem then really has a non-generalizable need, then that subsystem is allowed to branch on CMAKE_C_COMPILER_ID or ZEPHYR_TOOLCHAIN_VARIANT. My bet is that the generalizable cases would constitute the vast majority.

Your example of subsys/bluetooth/controller/CMakeLists.txt:63, is actually the only instance currently in Zephyr: grep -ERin 'zephyr_(cc|ld|compile|library).*_option' zephyr/subsys only finds that 1 match. And if we look at it:

zephyr_library_compile_options_ifdef(
  CONFIG_BT_CTLR_FAST_ENC
  -Ofast
  )

Would it really be so bad to replace it with:

zephyr_library_compile_options_ifdef(
  CONFIG_BT_CTLR_FAST_ENC
  toolchain_get_cc_ofast()   # or some better generic intent-based name
  )

?

That way we keep the logic in Cmake and not [some ad-hoc python tool + 1 more build step].

More reasons:

  1. The GCC command line is not a standard.
  2. GCC is not a lowest common denominator; it will be difficult to translate from GCC syntax to the syntax of more limited toolchains. Worse, semantic meaning is lost to the python tool as it would have to work without context.
  3. A robust build system should not give preferential treatment to any particular toolchain.
  4. A good Zephyr subsystem should be portable, and therefore limit its use of toolchain-specific flags, by instead relying on the intent-based cmake macros. This actually loosens the coupling between a subsys and the toolchain.
  5. The proposed python tool would not understand out-of-tree toolchains -- that we at Oticon use.
  6. This proposed python tool would consist of a bunch of fragile string/regex substitutions, each being a leaky abstraction where GCC is upheld as the one to be mimicked.

@mped-oticon
Copy link
Collaborator

This may be an issue worthy of TSC attention. @nashif Do you have input?

@SebastianBoe
Copy link
Collaborator

That is why the intent should be expressed as a cmake
macro/function. That takes care of the general case.

There is a misunderstading, I am not saying we should never use a
Zephyr abstraction, I am saying that flags that are supported by
most toolchains should not be wrapped with an abstraction, while
flags that are not portable should be.

What is designated as a portable and non-portable flag is up for
debate. For instance, -Ofast is currently not designated as a
portable flag, which is why we introduced
OPTIMIZE_FOR_SPEED_FLAG, which should have been used by
controller/CMakeListst.txt like this:

zephyr_library_compile_options_ifdef(
CONFIG_BT_CTLR_FAST_ENC
${OPTIMIZE_FOR_SPEED_FLAG}
)

An example of what is today considered a 'portable' flag would be
'-imacros', -ffreestanding, and any other flag that is
unconditionally added verbatim to the build today.

The GCC command line is not a standard.

No, it's not, but it's more standardized than any wrapper API
that Zephyr can invent.

GCC is not a lowest common denominator; it will be difficult to
translate from GCC syntax to the syntax of more limited
toolchains. Worse, semantic meaning is lost to the python tool as it
would have to work without context.

If there are any flags that can not be dealt with by the compiler
driver we can re-cassify them as non-portable. I believe this
will be the exception, rather than the rule.

A robust build system should not give preferential treatment to any
particular toolchain.

I disagree, using an existing CLI makes it easier for users to
read and write build scripts.

A good Zephyr subsystem should be portable, and therefore limit its
use of toolchain-specific flags, by instead relying on the
intent-based cmake macros. This actually loosens the coupling
between a subsys and the toolchain.

I disagree, portability can be achieved without intent-based
macros and the coupling is for some flags more useful than
harmful.

The proposed python tool would not understand out-of-tree
toolchains -- that we at Oticon use.

Non-gcc compatible out-of-tree toolchains will need to develop
their own drivers, just as they will need to develop toolchain
cmake portability build scripts.

This proposed python tool would consist of a bunch of fragile
string/regex substitutions, each being a leaky abstraction where GCC
is upheld as the one to be mimicked.

I don't see that this scheme is doomed to be fragile, and have
more leaky abstractions than a pure intent-based macro interface
would.

@carlescufi
Copy link
Member

@mped-oticon I agree that this will probably need discussion at the TSC level. Can you please send an email to the TSC mailing list to raise awareness and to request it being included in the next TSC meeting?

@nashif
Copy link
Member

nashif commented Oct 9, 2018

will put this on the agenda for next week. my point of view on this: Zephyr should support toolchains/compiler without any bias to one or another toolchain/compiler. We do need a portable way for supporting any compiler, wether in-tree or out-of-tree the same way. GCC is getting all the benefits because it was there first, but thats about it, once we have more compiler supported, this bias hopefully will go away.

@SebastianBoe
Copy link
Collaborator

My point of view is that we should bias towards the GCC CLI. It is familiar and well documented. The alternative to biasing against a CLI is to disallow direct usage of compiler flags, which would make the build system difficult to read and write.

@mped-oticon
Copy link
Collaborator

disallow direct usage of compiler flags, which would make the build system difficult to read and write.

Or you could replace the literal compiler flag(s) with a better-named, English, intent-based name :)
And if GCC has already chosen the perfect name, then we'll use it. It just gives the possibility to change it for each particular toolchain.

@SebastianBoe
Copy link
Collaborator

I don't know, how would that work?

This looks unmaintainable, and it is only changing 4 out of dozens of flags;

SebastianBoe@b27a9a8

@fnde-ot
Copy link
Collaborator

fnde-ot commented Oct 11, 2018

Those variables could contain multiple flags grouped by intent, such as desired warning levels or readable assembly, ...

It would leave us with a dozen variables such as:

COMPILER_FLAGS_MAIN
COMPILER_FLAGS_WARNINGS1
COMPILER_FLAGS_WARNINGS2
COMPILER_FLAGS_WARNINGS3
COMPILER_FLAGS_READABLE_ASM
COMPILER_FLAGS_STACK_CANARIES
COMPILER_FLAGS_FRAME_POINTER
COMPILER_FLAGS_NO_FRAME_POINTER
...

fx:
set(COMPILER_FLAGS_WARNINGS1
-Wextra
-Wunused
-Wno-unused-parameter
-Wmissing-declarations
-Wmissing-format-attribute
-Wold-style-definition
)
...

Macros/functions could also be used.

@mped-oticon
Copy link
Collaborator

I don't know, how would that work?

This looks unmaintainable, and it is only changing 4 out of dozens of flags;

SebastianBoe@b27a9a8

I think your diff looks very readable: An English description tied to what flag is needed to achieve that in GCC.
It exemplifies a very direct 1:1 mapping, so the intent is there but not very abstract/lifted.

I'd argue if you increase readability, you increase maintainability.
Granted, some toolchains would have these expand to nothing (which is fine), but having them verbosely named like that would increase understanding of the issue that we aim to solve. That would make it easier to port Zephyr to other toolchains, IMHO.

Then we can discuss implementation details;

  1. Should it be variables or macros, etc?
  2. There is no need (and generally can't be) a 1-to-1 correspondence (which your diff was) as that would not be abstracted enough. As a contrived example; in your diff, you could have chosen to collapse the two ENABLE_SPRINTF into 1, e.g. CC_WARN_SPRINTF or even more abstract, CC_WARN_SECURITY and CC_WARN_FORMAT. Picking the right level of abstraction/correspondence/convention is an art.

Finally, note that this does not only apply to the compiler but also the linker.
You'll find many more examples of GNU-assumptions in uses of zephyr_ld_options. Ideally, I would abstract whole sections of CC/LD flags, rather than having very fine-grained 1:1 mapping. Or maybe a mix -- it is up for discussion.

@SebastianBoe
Copy link
Collaborator

Zephyr has two API's for adding flags.

*_cc_option
*_compiler_option

one is used to express that the flag should be used if the toolchain supports it. And the other that the flag is a requirement (So optional or mandatory flag).

We need to retain this ability somehow ... silently dropping flags when the toolchain doesn't support it won't do.

@pfalcon
Copy link
Collaborator

pfalcon commented Nov 8, 2018

cc: @GAnthony as a TI guy.

@carlescufi
Copy link
Member

@tejlmand please close if you think this is not applicable anymore

@tejlmand
Copy link
Collaborator

@carlescufi yep, will try to go through current status to see if more needs to be done.

@stephanosio stephanosio changed the title Zephyr doesn't support TI Code Generation Tools Support TI Code Generation Tools Apr 27, 2022
@tejlmand
Copy link
Collaborator

tejlmand commented Oct 2, 2023

@yashi I believe the toolchain / compiler infrastructure used in Zephyr today provides a mechanism that allows you to implement CGT compiler support.

The template for compiler flags can be seen here:
https://github.com/zephyrproject-rtos/zephyr/blob/main/cmake/compiler/compiler_flags_template.cmake

basically a given set of properties are defined, and then the compiler CMake files populates those properties with their corresponding arguments.

An example on how gcc populates those properties can be found here:
https://github.com/zephyrproject-rtos/zephyr/blob/main/cmake/compiler/gcc/compiler_flags.cmake

If a compiler has many options in common with gcc, then it may inherit GCC's values and overwrite just those which are different, for example as clang does here:

include(${ZEPHYR_BASE}/cmake/compiler/gcc/compiler_flags.cmake)
# Now, let's overwrite the flags that are different in clang.

Other compilers, such as ARC MWDT, may create its own compiler_flags file:
https://github.com/zephyrproject-rtos/zephyr/blob/main/cmake/compiler/arcmwdt/compiler_flags.cmake

I believe this infrastructure also support the use-case in this issue.

@yashi please take a look, and close this issue if you believe it meets your needs.
Else give a comment on what is lacking in current Zephyr compiler infrastructure.

@yashi
Copy link
Collaborator Author

yashi commented Oct 4, 2023

@tejlmand It looks great!

Unfortunately I don't currently use CGT so it might be little while to submit CGT support. I'll close this issue for now and reopen it when I need it. I hope someone beat me to it.

@yashi yashi closed this as completed Oct 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Toolchains Toolchains Feature Request A request for a new feature
Projects
None yet
Development

No branches or pull requests

8 participants