Getting link errors with CMake - c

I'm getting multiple definition link errors after conditionally compiling platform-specific code.
My project is laid out like this:
/
|__+ include/
| |__+ native/
| | |__ impl.h
| |
| |__ general.h
|
|__+ src/
|__+ native/
| |__ impl.linux.c
| |__ impl.win32.c
|
|__ general.c
At the top of the general.c file:
#if defined(LIBRARY_PLATFORM_LINUX)
#include "native/impl.linux.c"
#elsif defined(LIBRARY_PLATFORM_WIN32)
#include "native/impl.win32.c"
#endif
I set up introspection in CMake in order to detect the operating system and define the corresponding constants. The thing is, I didn't want to maintain one CMakeLists.txt file in every directory, so I simply globbed all the .c files as suggested in this answer:
file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c")
Apparently, this is what is causing the problem. It seems to be compiling the code #included in general.c as well as the individual src/native/impl.*.c files.
CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h':
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h'
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here
How can I untangle this situation?

The best practice for that sort of cross-platform situation is to create two libraries, one for linux and one for windows and stop doing conditional includes. Each platform only compiles and links the relevant library.
The recommended way to do that with cmake is to stop globbing and just include each file. There are some situations where it can get confused and not realize that it needs to recompile. You can make an argument that non-changing legacy code won't have that problem.
If you really want to avoid doing either of these things, I would put the included code in a header instead of a c file. You don't really want the include guards so that people don't get it confused for something that should be used like a regular header. Put a bunch of comments in the file to warn them off of said behavior as well.

Related

Manually specifying include directory for Swift C module

I have a C library MyLib that I am trying to use in a Swift app. I want to use a local copy of the library, so I don't want to install it or add my bridge header to its files. I clone the library to Sources/ClibMyLib/MyLib so the package structure looks like this:
App
| Package.swift
| Sources/
| ClibMyLib/
| module.modulemap
| bridge.h
| MyLib/
| include/
| myLibHeader.h
| source/
| *.c
I specify bridge.h as the header in the module map:
module ClibMyLib {
umbrella header "bridge.h"
link "MyLib"
export *
}
The problem is that the include directory of MyLib is not visible to bridge.h So if bridge.h looks like this:
#include "myLibHeader.h"
it fails to build since it can't find myLibHeader.h. If I specify the path from bridge.h to the local copy like this:
#include "MyLib/include/myLibHeader.h"
then any transitive includes in myLibHeader.h still fail.
This would be very easy to solve in a C build, I would just add MyLib/include as an include directory. I haven't been able to find a way to do something similar in Swift - most guides I have found install the library and include from /usr/local/include/.
Are my only options to place bridge.h in the library's include directory or to install the headers to /usr/local/include? Adding bridge.h to the library is not ideal, the include directory file structure is more complicated than the simple example I gave. I just want to be able to manually specify an include directory.

Does the linker look for the header file

When compiling C source files, we include header files for example using #include "myheader.h".
The pre-processor will expand this header file before compiling the file. However, how does it find this header file exactly? I believe, the path of the header files is passed as an argument to the linker using -I for example to gcc.
I always thought that the linker only runs after compilation. So does the linker actually run before, to find stuff such as header files, and after compilation to combine various object files etc. ? Thanks
Headers mostly declare meta symbols, and function prototypes that allow the compiler to match/check cross compilation unit calling of functions.
All actual symbols interesting to a linker are defined in C files. The compiler can use preprocessor symbols (#defines) during codegeneration, but they are then inlined in the generated code.
Likewise, in the case of C++ inline methods or templates, code is generated by the compiler on the place where they are used.
This means the linker does not need anything from the headers, anything that would be needed is already processed by the compiler into the generated code stream (to the assembler or object file compiler output).
So no, includefiles are not relevant to the linker.
Below a stripped down version of the way from sources to executables.
+-------------------------------+
| sources (typical .c/.h files) |
+-------------------------------+
|
V
pre-processor
|
V
+-------------------------------+
| intermediate sources |
+-------------------------------+
|
V
compiler
|
V
+-------------------------------+
| object files (.o) |
+-------------------------------+
|
V
linker
|
V
+-------------------------------+
| executables/shared libraries |
+-------------------------------+

How to properly configure include paths with simple CMake project

I have a CMake project for cross compiling executables for the STM32. The project structure includes folders for the various dependencies required, where the sources and header files are included in those folders. The CMakeLists.txt file to build the project is as easy as setting up for cross compilation and then globing together the sources from each dependency and user code, followed by setting the locations of all the headers with include_directories. Finally, add_executable is used to combine everything and build the binary.
I realize, this is probably not the most optimal way to do this (should probably build the deps as libraries), but it does work for now.
The issue comes in with a dep that has many layers of subdirs (lwIP), and the source and header files contain include statements that are references to levels of subdirs in that dep. For example, the lwIP file structure looks like:
> LwIP
| include
| lwip
| err.h
| netif
An lwIP source file (or header file!) might include "lwip/err.h". Of course, the preproc cannot find this file because the relative path makes no sense to it.
How should I configure this project such that these includes can be used without modifying source or header files?
The usual way to get around this issue is to create your own find module i.e. FindXXX.cmake (in your case it is FindLwIP.cmake) so that you can create LwIP_INCLUDE_DIRS variable within the package.
set(LwIP_INCLUDE_DIRS
${CMAKE_CURRENT_LIST_DIR}/../LwIP/include
${CMAKE_CURRENT_LIST_DIR}/../LwIP
${CMAKE_CURRENT_LIST_DIR}/../LwIP/include/XXX)
.
.
(omitted..)
.
.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LwIP DEFAULT_MSG LwIP_INCLUDE_DIRS LwIP_SOURCES LwIP_HEADERS)
With the above find module, your application can cleanly include the package and use the variables that are created by the find the module.
find_package(LwIP REQUIRED)
.
.
(omitted...)
.
.
include_directories(LwIP_INCLUDE_DIRS)
add_executable(${PROJECT_NAME}.elf ${SOURCES})
Since your work is related to STM32 & cmake, let me give you a great reference which will be a nice starting point for your work as well.
https://github.com/ObKo/stm32-cmake.git
Hope this helps.

Including Libraries in Multiple Files C Lang

I am working on a C project and I like to keep myself organised. Thus, I have got multiple header files, files with functions for that header files and a main file.
|- Header Files
| |- hash_table.h
| |- linked_list.h
| |- dictionary.h
|- Source Files
| |- main.c
| |- hash_functions.c
| |- list_functions.c
| |- dictionary_functions.c
Will it be any problem if I include libraries such as #include <stdio.h> in each of that function file? Will it affect by any means the efficiency of my program?
No, there would not be any problem if you include same header file in multiple files.
When any header file is written it is written to avoid multiple inclusion.
To avoid multiple inclusion, macro pre-processors are often used. One such mostly used way is given below.
#ifndef SOME_SYMBOL
#define SOME_SYMBOL
// actual code goes here.
#endif
For example see the code of stdio.h file for Linux at : https://github.com/torvalds/linux/blob/master/arch/powerpc/boot/stdio.h
All modern headers use header guards. This means that the header checks if it has been included before and then skips it. Also the compiler is smart enough to figure out which functions defined in a header you actually use and only include those in object code.
No, the include file is a description of the library. The library itself is a separate binary file that is linked in the final stages of program assembly
No problems.
Standard header files are written that way.
See: http://en.wikipedia.org/wiki/Include_guard
Mutliple file Inclusion will not effect you untill you have a INCLUSION GAURD.So by thi sYou can also do one easy thing, That is by having Single header file (suppose includes.h) which will have all include files So that you can eliminate the Order of Inclusion problem with the cost of compilation time.

Create a build environment for "C" project to dynamically select folders during compile time

Lets say my folder structure is something like this ..
+-- Application
|
+-- MICRO_CONTROLLER_1
|
+-- MICRO_CONTROLLER_2
|
+-- MICRO_CONTROLLER_3
and i have a compile switch ( SELECT_MICRO) set to #define SELECT_MICRO == MICRO_CONTROLLER_1 , then my project should build application with driver files in MICRO_CONTROLLER_1 , similarly if #define SELECT_MICRO == MICRO_CONTROLLER_2 , then application should build application with driver files in MICRO_CONTROLLER_2
Please let me know if there template to achieve the above.
You can export that particular path of the folder you want to build and supply the path to the executable. You can get further info. in this thread.
How I could add dir to $PATH in Makefile?
Or simply maintain different Makefiles to make different builds and use make -f to run that particular makefile.
I hope this is what you finally want to perform.
Typically you would define your pre-processor definitions to tell the pre-processor to include only, for instance, MICRO_CONTROLLER_1 blocks of code and ignore everything else.
Something like the following should suffice:
#if defined(MICRO_CONTROLLER_1)
// Block of code that is only available to MICRO_CONTROLLER_1
#elif defined(MICRO_CONTROLLER_2)
// ...
// All other microcontrollers you are supporting would follow this structure.
#endif
Then you would need to define MICRO_CONTROLLER_1. If you're using an IDE for development, there is typically a project option for pre-processor directives. This is where you would define MICRO_CONTROLLER_1. You could then create different "configurations" - one for each of the microcontrollers you are targeting.
This can only work if the directories have only include files. #define is a preprocessor directive. If the directories have source files, you need to solve it at the build system layer, not the preprocessor layer.
Assuming it's just include files, you'd just #include SELECT_MICRO # "Interface.h"

Resources