I feel like I'm missing some key idea with this one.
I have a library that I'd like to create a CMakeLists.txt file for. I want to link against it with different applications.
This library expects a conf.h file to be defined. The application has to provide this. The library expects it. What is this relationship called?
My current solution in CMakeLists.txt is to have a variable like:
...
target_include_directories(lib PUBLIC
${CONF_DIR}
)
And then have CONF_DIR be defined by the application. This is uncool, because I can't have multiple applications linking against it.
The only other alternative is to keep a copy of the entire source library inside the application folder, which is also uncool.
I'm looking to maximize reusability. How do I approach this?
Side note: For anyone who's familiar, the library in question is STM32Cube's HAL library, and the pesky file is stm32h7xx_hal_conf.h.
This is a very common approach, when a library requires configuration. FreeRTOS would be another example.
I don't see the issue with modifying the target_include_directories for the library from the App's CMakeLists.txt.
Usually, I create a function to handle the library set-up. The call site would look something like this:
add_stm32_hal_lib(
PATH drivers/STM32H7xx_HAL_Driver
EXTRA_INCLUDES path/to/config
)
# ...
target_link_libraries(app PUBLIC stm32_hal)
The contents of the EXTRA_INCLUDES parameter get shoved into target_include_directories of the static library.
You can't do anything about this, so you'll have to copy the library code.
The header file is used during library compilation stage, so its code ends up being hardwired into the final binary. Because of this, if you want to change some parameters from the header, you need to recompile the library from scratch.
Ideally, the library should be rewritten in such way, that all parameters that are contained in the header can be set up dynamically, during the runtime, using some additional configuration API.
Related
I am currently learning the C programming language and I'm having some issues with importing modules I created.
I created a small module to read with fgets and flush the buffer from stdin perfectly and I don't want to keep writing the code every single time. I just want to import this small module like I used to do in Python. I didn't knew how because I'm not using an IDE. I'm just compiling with gcc in terminal and using a text editor. I tried to search with Google,but in vain.
You should create a header for your module that declares the functions in the module – and any other information that a consumer of the module needs. You might call that header weekly.h, a pun on your name, but you can choose any name you like within reason.
You should create a library (shared or static — that's up to you) that contains the functions (and any global variables, if you're so gauche as to have any) defined by your module. You might call it libweekly.so or libweekly.a — or using the extensions appropriate to your machine (.dylib and .a on macOS, for example). The source files might or might not be weekly.c — if there's more than one function, you'll probably have multiple source files, so they won't all be weekly.c. You should put this code (the header and the source files and their makefile) into a separate source directory.
You should install the header(s) and the library in a well-known location (e.g. $HOME/include for headers and $HOME/lib for the library — or maybe in the corresponding directories under /usr/local), and then ensure that the right options are used when compiling (-I$HOME/include for the headers) or linking (-L$HOME/lib and -lweekly).
Your source code using the module would contain:
#include "weekly.h"
and your code would be available. With shared libraries in $HOME/lib, you would have to ensure that the runtime system knows where to find the library. If you install it in /usr/local, that is done for you already. If you install it in $HOME/lib, you have to investigate things like /etc/ld.so.conf or the LD_LIBRARY_PATH or DYLIB_LIBRARY_PATH environment variables, etc.
You need to create a header file (.h) with your function declarations types and extern variables. Then in the program where you want to use those functions include this .h file and and add the compiled .o file (with your functions) to the object file list. And you are done.
I'm working with pocketsphinx. It comes in 2 dlls. sphinxbase.dll and pocketsphinx.dll. pocketsphinx.dll calls on functions in sphinxbase.dll. I'm going to be calling functions in both. I'd like to know the easiest way to merge both source files into producing a single dll.
I've tried this before but I run into the problem of pocketsphinx using sphinxbase leading to a warning/error about importing functions I'm trying to export.
What's the common solution to get around this?
Should I remove the dllexport tags from sphinbase and then wrap those functions inside other functions that I then export?
Example
//inside sphinxbase
SPHINXBASE_DLL_EXPORT
void sphinxbasefunc();
//inside pocketsphinx
POCKETSPHINX_DLL_EXPORT
char* decode(ps_decoder_t decoder)
{
...
sphinxbasefunc();
...
}
Then I would remove the SPHINXBASE_DLL_EXPORT macro and create a wrapper that I would then export.
//inside sphinxbase
void sphinxbasefunc();
WRAPPER_DLL_EXPORT
void sphinxbasefunc_wrapper() { sphinxbasefunc(); }
This solution I think is naive on my own part though. Theres dozens of functions I would need to wrap if I took this route.
One thing to realize is like an exe, a dll is just a collection of one or more object files bound into a package. Combining object files into dlls/exes is the linker's job. If you want to combine your two dlls into one, combine the object files that make up your two dlls into one dll. When you do that your references will no longer be to dlls, but directly to the objects themselves (source code changes will be required, but mostly this is removing dllimports), so it should be a much more direct process (include the header, make sure the object is included in the link). You only need to export those functions required by consumers of the final dll. Basically put the source for both dlls into one project. I'm assuming of course that you have the source for these dlls (which is how it appears from the url given). If you end up with circular dependencies you may have to create some forward declarations or additional header files to keep the compiler happy.
Situation:
i have a static library "lib1.a" ;
a second static library "lib2.a" that uses the functions of "lib1.a";
an application that directly uses just the functions of "lib2.a".
When i link the application i have to pass to the application dependencies also "lib1.a" even if the application do not calls directly none of lib1 functions. Lib2 is a sort of more high level wrapper library.
Is there a way to link lib1 inside lib2 (a sort of intermediate linking) so that the "app" does not even know about the existence of lib1?
I know that i can scompact lib1.a and include the objects files inside lib2.a but is there another way so that is done automatically and JUST the USED object files are included inside lib2? Linke when you link the final app.
{app} -uses-> {lib2} -uses-> {[lib1]}
Cheers,
Davide
is there another way
No, there is not (on any UNIX-like system I know of).
The best you can do, when using GNU-ld or gold, is to write a libcombined.a as a linker script, containing -l2 -l1, and point the application to it.
I am using the DDK to build a project. Several of the build targets generate small internal libraries -- for simplicity, let's call them LibA.lib, LibB.lib, and LibC.lib. But the code for LibA references code from LibB and LibC. To use LibA in a project, you also need to include LibB.lib, and LibC.lib to resolve all of the dependencies. What I want to do is link LibB and LibC into LibA such that a user only needs to include LibA.lib. How can I accomplish this?
The SOURCES file for LibA looks something like this:
TARGETNAME=LibA
TARGETTYPE=LIBRARY
TARGETPATH=..\lib\$(DDKBUILDENV)
INCLUDES = .; \
..\LibB; \
..\LibC; \
$(CRT_INC_PATH) \
$(SDK_INC_PATH)
SOURCES = LibA_main.cpp \
LibA_file2.cpp \
LibA_file3.cpp
I understand that you can manually link libraries with link.exe; e.g.,
link.exe /lib LibA.lib LibB.lib LibC.lib
But if possible, I would like some way to achieve this same effect as a part of the build process for LibA, because some targets at a later point of the build process rely on LibA.
Thanks!
I realize this is a late answer and it may not even be what you want in the end. However, ddkbuild.cmd has a pretty nifty mechanism to run actions before and after a build inside a particular directory.
We use this in one of our driver libraries which necessarily gets built as a number of static libraries and as a final step linked into one big static library much like you want. If you are able to use something like ddkbuild.cmd in your project, this would provide a solution and it's a solution that would work in automated builds, too.
NB: as far as I'm aware you cannot achieve what you want directly with build.exe. However, it's well possible that with some make (NMake) file acrobatics you could achieve a similar result. So the question is whether it's worth reinventing the wheel when there is one already.
I have encountered the same situation as you. Google a lot of and still have no solution. Fortunately, I found a way to resolve it finally. You can try it, add the below statement in your libA sources file.
LIBRARIAN_FLAGS = $(LIBRARIAN_FLAGS) libB.lib libC.lib
The lib utility can combine libraries. Using your example, the command would be:
lib /out:CombinedLib.lib LibA.lib LibB.lib LibC.lib
How can I locate a C library header file from a Makefile.PL?
There is ExtUtils::Liblist to find libraries, but I can't see the equivalent for header files.
Devel::CheckLib is what most authors seem to be use for that. It checks both for the existance of libraries as well as header files, as those libraries are probably useless without them.
Why not write a small lib to do this (and let it live in inc/lib/FindHeaders.pm or some such under the top level of your package dir). Just use Config (see incpath) along with File::Find and glob and you should be able to have a small library which can walk your default include path and map a hash of header files on your system, returning it to a call from Makefile.PL. It would be trivial to extend this to include non-standard include paths as well with a constructor argument to your lib. Easy peasy.