-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
cmake: Use plain CMake instead of Zephyr's custom interface #8439
Comments
Issue #8614 further shows that wrapping of CMake commands limits the feature set of CMake. |
Additionally, another issue with wrapped function, is that the behavior of the wrapped functions are not stable as their internals can change between commits. This is seen in the suggested fix, referred to by this comment: The CMake API is in contrast very stable, and behave consistently. Also, wrapping if CMake API this way, limits the feature set of CMake's API, and thus, each time such blocked feature is needed, a new zephyr wrapper gets introduced. |
RFC for zephyrproject-rtos#8439 - This commits adds a new function for creating and populating a list with IFDEF and IFNDEF as well as specifying source to ensure default path pre-fixing. - function is: zephyr_list Signed-off-by: Torsten Rasmussen <[email protected]>
RFC for zephyrproject-rtos#8439 - This commits adds a new function for creating and populating a list with IFDEF and IFNDEF as well as specifying source to ensure default path pre-fixing. - function is: zephyr_list Signed-off-by: Torsten Rasmussen <[email protected]>
I'm not sure what to make of this, could you change the title to make it clear whether this is a; feature request, |
Consider it a "reverse" feature request. The request is to remove the mentioned wrapped functions, and instead stick to default CMake functions, which already provides what is needed. Only create and maintain zephyr functions where a new functionality is really useful, e.g. like the zephyr check compiler flag functionality. This will also ease the entry barrier for new comers who already know the CMake language. By using plain cmake for target handling we avoid having to create new wrapper functions whenever a new CMake keyword / function argument needs to be supported, such as: And also we avoid e.g. PR's as: There are probably more out there. |
RFC for zephyrproject-rtos#8439 - This commits adds a new function for creating and populating a list with IFDEF and IFNDEF as well as specifying source to ensure default path pre-fixing. - function is: zephyr_list Signed-off-by: Torsten Rasmussen <[email protected]>
As a newcomer to zephyr, I can attest that the whole wrapper macro thing is very frustrating. |
@meuter I agree, but CMake adheres to an opinionated I-will-deduce-everything-for-you mentality that collides with the nitty-gritty specifics required to build an OS. So I see the reason for why things are the way they are. Add to that, the need to support multiple wildly-different toolchains... If you see improvements, feel free to send a Request-For-Comments pull request. |
@mped-oticon I can very well understand the kind of details and complexity you're talking about and indeed it's bit of a culture clash. However, I think a more "transparent" approach would be easier to grasp. Currently the zephyr_xxx() and zephyr_library_xxx() macros are just trying to hide some of the complexity and are not really adding much to what cmake offers out of the box. Another advantage I see in keeping with the more idiomatic cmake way of doing things is that it would make porting existing libraries to zephyr much easier (most are coming with CMakeLists.txt these days). You'd simply add_subdirectory(/path/to/external/library) and you should be mostly good to go. In any case, once I have a bit more experience with zephyr (as I said I'm a newcomer), as you suggest I'll send a Request-For-Comments pull request. |
@tejlmand I am pretty sure this can be closed with resolution "won't do"; right? |
I wouldn't say so, but it's down on the prioritization list compared to other work. Also I think it's nice to keep open for other new comers to Zephyr who might be experienced CMake developers that this is something we are aware about. |
Hah, okay then. I'm officially taking bets on if this ever gets done :) |
Very interesting discussion. Is there an idea, how that is handled for "third-party/external libraries"? |
Add zephyr_interface_library_include_directories to Zephyr interface library API. As Zephyr ecosystem expands, more libraries are added. As the number of Zephyr libraries grows, many are only consumed by specific applications and not required by any subsystem. When we add a new library to Zephyr, we use zephyr_library_* APIs and link against zephyr_interface. Which works good, except that it adds all its PUBLIC and INTERFACE scoped information to every other subsystems / libraries depending on zephyr_interface. As a result, the number of include directories passed to a subsystem/library is increasing. One thing zephyr_interface_library_* provides is access to the library header files to the 'app' without polluting the subsystem build options. Given that set(MOD_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) We can currently do zephyr_interface_library_named(libsome) target_include_directories(libsome INTERFACE ${MOD_DIR}/include) zephyr_library() zephyr_library_include_directories(${MOD_DIR}/private/) zephyr_library_sources(${MOD_DIR}/src/some.c) zephyr_library_link_libraries(libsome) This enables the 'app' to compile using libsome header files. This commit changes the second line to zephyr_interface_library_named(libsome) zephyr_interface_library_include_directories(libsome ${MOD_DIR}/include) This doesn't gain any technical functionality but the user experience is much more straightforward. BTW, I'm aware of zephyrproject-rtos#8439. Signed-off-by: Yasushi SHOJI <[email protected]>
Hi @tejlmand, This issue, marked as an Enhancement, was opened a while ago and did not get any traction. Please confirm the issue is correctly assigned and re-assign it otherwise. Please take a moment to review if the issue is still relevant to the project. If it is, please provide feedback and direction on how to move forward. If it is not, has already been addressed, is a duplicate, or is no longer relevant, please close it with a short comment explaining the reason. Thanks! |
What is the status of this? |
Btw, not using a CMAKE_TOOLCHAIN_FILE is also part of not using plain CMake. This would still be a nice to have regarding integration with Conan (see #31745) and probably other projects. I resorted to copy paste the compile flags used by Zephyr in a Conan profile where I could just have pointed to the toolchain file if it was there. Then I discovered that I think I understand where you're coming from, but when we recently started our new project, we thought "cool, Zephyr is CMake based, it'll be easy to integrate with our current code". Then I was disappointed to see it's yet another project working around CMake in its own unique, incompatibles ways. Reading the few issues around this here makes it clear there are actual reasons about this, and I understand that there's a lot of cmake code that would need to evolve, but it would be nice if there were some plan to move toward a more standard way of doing things. At least providing The KConfig configuration system could be replaced by cmake variables. And then maybe merging some features upstream? The global compiler flag cache is a nice thing and could maybe be useful to other projects. For the compiler features, maybe using Just my 2 cents here. All in all, it's working. I'm just sad that in 2024, it's still complicated to integrate two unrelated C++ projects even though they both use CMake. Best wishes for 2025 ;) |
My main problem with the Zephyr approach of using CMake is, that it prohibits a lot of features in CMake. In a lot of projects I use CMake and I havn't seen so far anything special, that would justify the "weird" use of CMake that I'm seeing in Zephyr (but of cause, I don't know all the internals). Beside the home grown compiler detection (which then requires the weird
There seems to be even more redundant features being implemented in Zephyr, that already exists in CMake (where it is usually very well documented):
I wonder, why Zephyr is not just used as a library (maybe having a function to configure and create an object library to be used). Something along the lines of:
|
Zephyr are having their own wrapped versions of many CMake commands.
The commands looks similar, many of them are simply re-arranging words you need
to type.
Some drawbacks I see with the current approach are:
use CMake's online documentation as reference, the user also has to read/learn
Zephyr additional set of API's.
it
e.g. zephyr_sources(...) => target_sources(zephyr ...)
The Zephyr just moves from being target name, to be the function name instead
language.
In CMake you will do:
add_library(MyLib ...)
target_sources(MyLib ....)
target_include_directories(MyLib ...)
This is with slight variation similar to an OO language, where one might have done:
MyLib = new library()
MyLib.sources(...)
MyLib.include_directories(...)
The object name in CMake is just placed as argument.
but in Zephyr, the object/variable name has disappeared:
zephyr_library()
zephyr_library_sources(...)
zephyr_library_include_directories(...)
Example of functions with the words re-arranged,
Instead of writing target_sources(zephyr PRIVATE ...), I have to write
zephyr_sources(), so target name zephyr is just part of the function name.
Instead of target_sources( PRIVATE ...), the target name is hidden and I
need to write zephyr_library_sources(...).
I still need to know the difference between zephyr_sources and
zephyr_library_sources, where CMake just has a single API.
One might argue, that you avoid to know the difference between PRIVATE, PUBLIC, and INTERFACE.
But those keywords are easy and useful to know:
PRIVATE : The content following is only used by the library.
PUBLIC : The content is used by the library and those who links to it.
INTERFACE: The content is only used by those who links to the library.
Zephyr's wrapped commands doesn't completely remove those keywords, it just
places them elsewhere, e.g.
zephyr_library_named() = add_library( STATIC "")
zephyr_interface_library_named() = add_library( INTERFACE)
The use of macros must be done with care:
As example, a user cannot use the variable: name,
as this name is used by the Zephyr macros,
Example, do the following in any CMakeLists.txt, and you'll see the macro
manipulates ${name}.
(CMake functions doesn't suffer from this problem):
set(name "MyName")
message("Value of name=${name}") # The value of name=MyName
zephyr_library()
message("Value of name=${name}") # Now the value of name is something else
I acknowledge that some commands are providing an easier out-of-the box
understanding by providing _ifdef versions, but I believe this can also be
achieved without the drawbacks mentioned above.
List of Zephyr commands that wraps CMake commands and their CMake equivalent:
zephyr_sources = target_sources(zephyr PRIVATE)
zephyr_include_directories = target_include_directories(zephyr_interface INTERFACE)
zephyr_system_include_directories = target_include_directories(zephyr_interface SYSTEM INTERFACE)
zephyr_compile_definitions = target_compile_definitions(zephyr_interface INTERFACE)
zephyr_compile_options = target_compile_options(zephyr_interface INTERFACE)
zephyr_link_libraries = target_link_libraries(zephyr_interface INTERFACE)
zephyr_library() = add_library( STATIC "") # With a library name based upon the folder
) = target_include_directories( PRIVATE )zephyr_library_named() = add_library( STATIC "")
zephyr_link_interface() = target_link_libraries( INTERFACE zephyr_interface)
zephyr_library_sources() = target_sources( PRIVATE )
zephyr_library_include_directories(
zephyr_library_link_libraries() = target_link_libraries( )
zephyr_library_compile_definitions() = target_compile_definitions( PRIVATE )
zephyr_library_compile_options() = target_compile_options( INTERFACE )
zephyr_interface_library_named() = add_library( INTERFACE)
EDIT: This is part of umbrella issue: #8827
The text was updated successfully, but these errors were encountered: