On Mon, 23 May 2016 13:49:14 +0000
Wagner Martin <martin.wag...@neuberger.net> wrote:

> Hi @all,
> 
> I'm quite new to CMake. If I've made a mistake or something is much
> easier to solve, please tell me.
> 
> I'd like to use CMake in embedded development (Build System: Linux,
> Target: ARM Microcontroller) to get rid of complicated makefiles.

Good thing! 

> We're building multiple devices where stuff like embedded rtos and
> peripheral drivers are identical, so I'd like to separate this part
> from the user application. I've achieved that by creating an object
> library out of all source and header files, and packing those files
> using CPack. This archive is then statically linked against the user
> application.
> 
> So far this worked fine. However, now I have to use driver functions
> in the rtos source code and vice versa, resulting in
> cross-dependencies for header files:
> 
> <drivers/uart.c>
> 
> #include uart.h
> #include terminal.h
> 
> function() {}
> 
> <os/terminal.c>
> 
> #include terminal.h
> #include uart.h
> 
> function() {}
> 
> How do I resolve something like this? Right now CMake evaluates the
> compiler includes in the order that subdirectories are added. This
> gives me an compilation error in uart.c that terminal.h cannot be
> found.

This is not a cmake-problem, but seems to be a code-structure-issue.

I'm guessing here: if terminal needs the uart-code shouldn't it be the
uart-code filling in a terminal-function. Interface vs. implementation?
Could you elaborate more on how terminal and uart are linked?

Regarding cmake: I suggest you stop using include_directories() and
start using target_include_directories() and
target_compile_definitions() instead of add_definitions().

Limiting yourself to this way of doing libraries and targets, cmake will
force you to structure your code in a more standard way - and will
provide you with clean visibility between different targets.

Could you provide a working, stripped down example to show the problem
provided via github (in an example repo).

More comments below.
 
> Some excerpt of my project. I've tried to keep the example as simple
> as possible.
> 
> My directory structure looks something like that:
> /
> CMakeLists.txt
> src +
>     +CMakeLists.txt            (1)
>     +drivers+
>     |       +uart.c
>     |       +uart.h
>     |       +...
>     |       +CMakeLists.txt    (2)
>     +os-----+
>     |       +terminal.c
>     |       +terminal.h
>     |       +...
>     |       +CMakeLists.txt    (3)
> 
> 
> (1):
> 
> SET(drivers "drivers")
> SET(terminal "terminal")
> 
> SET(drivers_lib ${drivers})
> SET(terminal_lib ${terminal})
> 
> SET(ARCHIVE_INSTALL_DIR lib)
> SET(INCLUDE_INSTALL_DIR include)
> 
> SET(headers_private "_headers_private") # internal headers
> SET(headers_public "_headers_public")   # public headers go into
> package
> 
> ADD_SUBDIRECTORY(${drivers})
> ADD_SUBDIRECTORY(${terminal})

I think it is common practice now to use lower-case for cmake-commands
now. 

> ## drivers
> 
> ## ---- Sources
> -------------------------------------------------------------------
> SET(sources "uart.c"
> )
> 
> ## ---- Header includes
> -----------------------------------------------------------
> SET(headers "${CMAKE_CURRENT_SOURCE_DIR}/" 
> )
> SET(${drivers}${headers_public} ${headers} PARENT_SCOPE)
> 
> INCLUDE_DIRECTORIES(${headers} 
>                     ${${terminal}${headers_public}}
> )

While the ${${var}${var2}} (seems to) work, it is error-prone, IMHO.

Standard cmake-commands can work with relative paths and are evaluating
them correctly taking into account ${CMAKE_CURRENT_SOURCE_DIR} (most of
the time. So you could use ../uart in terminal/ - but it would be
better if it comes indirectly via target_include_directories() and
target_link_libraries()

>[..]
> 
> And finally this creates the package in root directory CMakeLists.txt:
> 
> SET(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackOptions.cmake)
> # CPackOptions.cmake contains package file name SET(CPACK_GENERATOR
> "TBZ2") INCLUDE(CPack)

Due to the circular header-dependency the binaries of terminal and uart
should have the same mutual dependency. In this case you could build
them in within one target.

regards
--
Patrick.

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake

Reply via email to