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.
Related
Let's assume the following project structure composed of one executable in src and two libraries, lib1 and its dependency lib1_dep:
+--src/
| |
| +--Makefile.am
| +--main.c
|
+--lib/
| |
| +--Makefile.am
| +--library1.c
| +--library1.h
+--lib_dep/
| |
| +--Makefile.am
| +--library1_dep.c
| +--library1_dep.h
+--Makefile.am
+--configure.ac
The contents of the files are
configure.ac
# Add libraries dependance
AC_CONFIG_SUBDIRS([lib_dep])
AC_CONFIG_SUBDIRS([lib])
# Add src files
AC_CONFIG_FILES([Makefile
lib_dep/Makefile
lib/Makefile
src/Makefile
])
Makefile.am
SUBDIRS = lib_dep lib src
lib1_dep/Makefile.am
lib_LTLIBRARIES = lib_libdep.la
# Dynamic library
lib_libdep_la_SOURCES = library1_dep.c library1_dep.h
lib_libdep_la_LIBADD =
# Compiler options.
lib_libdep_la_CPPFLAGS = $(AM_CPPFLAGS)
lib1/Makefile.am
lib_LTLIBRARIES = lib_lib.la
# Dynamic library
lib_lib_la_SOURCES = library1.c library1.h
lib_lib_la_LIBADD = $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
lib_lib_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h
src/Makefile.am
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(AM_LDADD) $(top_builddir)/lib/lib_lib.la $(top_builddir)/lib_dep/lib_libdep.la
# Compiler options.
main_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib_dep/lib_dep.h -I$(top_srcdir)/lib/lib_lib.h
Observation
The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.
Question
Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?
Thanks
The build and install work well but I doubt I do it properly. The main program only uses functions defined in lib (not in lib_dep), so it looks strange that I have to also diretly link the main program to lib_dep. I would like your feedbacks on this please.
It is system-dependent whether indirect shared-library dependencies need to be included in the link. On Linux, they do. Compare to the situation with static library dependencies, which absolutely need to be included in the final link, on any system.
However, since you are using libtool, in a context where you can rely on its generated .la files to be available, you shouldn't need to provide explicitly for linking indirect dependencies. Libtool can handle that for you.
Is there a way to build/compile lib so that I don't have to add the LDAPP and CPPFLAGS related to lib_dep when I build y main program (src/Makefile.am) ?
That's actually two separate questions, one for LDADD and one for CPPFLAGS.
The CPPFLAGS are relevant only for compilation, not linking. Roughly speaking, if the main program's sources #include any headers from lib_dep/, whether directly or indirectly, then it is necessary for its CPPFLAGS to contain an -I flag for that directory. Otherwise, not.
An indirect inclusion would be if main.c includes library1.h and library1.h includes library1_dep.h.
Since you are using libtool to build both libraries, and consistently declaring link dependencies by putting the appropriate libtool archives in the LIBADD / LDADD variables, you do not need to specify the indirect library dependency in the main program's LDADD. libtool can and will figure out the indirect library dependency and add it to the main program's link if needed, and at the correct location in the link command.
Thus, if the main program has neither a compile-time dependency nor a direct link dependency on libdep, then its Makefile.am could look like this:
bin_PROGRAMS = main
main_SOURCES = main.c
main_LDADD = $(top_builddir)/lib/lib_lib.la
main_CPPFLAGS = -I$(top_srcdir)/lib
NOTE: it is not wrong to add $(AM_LDADD) to main_LDADD or to add $(AM_CPPFLAGS) to main_CPPFLAGS, as in the version of this Makefile.am presented in the question, but that is useful only if you've actually defined values for those AM_* variables.
NOTE2: Your -I flags should specify directories to search for header files, not the names of specific header files.
I want to make a public source library in C and I've been having a joyous time trying to work with both Makefiles and CMake. I like the simplicity of having one makefile per build partition but it's not cross-platform. I like the fact that CMake is cross-platform and although I hate the syntax types the language uses (I can get over that I guess..) it's the fact that when building, CMake floods my folders with a f*** tonne of cache files and I can't seem to change where they go. I would like to go with CMake since it seems to be more industry standard.
I like my builds in folders; Everything I care about in a seperate folder from all the build specific files that need to be generated. In visual studio I have this build structure and I would like to replicate it.
SolutionDir:
┝ Builds/
| ┝ Inter/ #For intermediate files
| | ┝ Debug/
| | | ┕ lib.o
| | ┕ Release/
| | ┕ lib.o
| ┝ Debug/ #For the debug build files
| | ┕ ProjectName/ ... .exe
| ┕ Release/ #For the release build files
| ┕ ProjectName/ ... .exe
┕ ProjectName/
┕ Source/
| lib.h
┕ lib.c
I cant even figure out how to make a sub directory in either systems for the build folder side, of course you can include sub directories for finding the source code so there must be a way? Any help would be greatly appreciated, I've been at this for too long now.
You can do whatever you want with makefiles, but since you ask about cmake, the only way to do it is to run the build from the build folder. In other words, you do this (assuming that you have SolutionDir/CMakeLists.txt):
cd SolutionDir
mkdir Builds
cd Builds
cmake ..
make -j8
(or whatever make command that you want). The Builds directory can be anywhere you want, it doesn't have to be within SolutionDir. You pass the directory containing the CMakeLists.txt file to cmake.
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.
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"
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.