I'm trying to link my kernel module with an external static lib, like this:
obj-m += my_prog.o
my_prog-objs := some/path/lib.a
# all the standard targets...
For some reasone, the above Makefile doesn't compile my_prog.c at all, and the resulting module doesn't contain its code. Certainly, if I remove my_prog-objs line, my_prog.c gets compiled.
What's wrong with such an approach in a Makefile?
You must create a synthetic name as well as the source file and it's object name. You can not use my_prog.o directly as there are rules to make it from source. Here is an sample,
obj-m += full.o
full-src := my_prog.c
full-objs := $(full-src:.c=.o) lib.o # yes, make it an object.
Libraries are only supported from some special directories. Your object should be named lib.o_shipped and placed in the same directory. So, you need to take the external library and provide it locally as a shipped version. You need two object files; one is your compiled 'C' code/driver and the other is it linked together with the library.
The above is relevant to 2.6.36 kbuild infra-structure. The current documentation is in modules.rst section 3.3 Binary Blobs. I think the technique above will still work for libraries as opposed to just objects.
When you create the my_prog-objs list, you tell kbuild to use only the object files in that list. kbuild will no longer compile my_prog.c, and including my_prog.o in my_prog-objs results in a circular dependency. Instead, you need to create a unique obj-m and include both my_prog.o and /path/lib.a in its objs list. For example:
obj-m += foo.o
foo-objs += my_prog.o /path/lib.a
Took me about 2 hours to figure out why my module was doing nothing!
You're overriding the default my_prog-objs, which is just my_prog.o. Instead of replacing the contents with the library, add the library to the default:
my_prog-objs := my_prog.o some/path/lib.a
Hopefully you're not trying to link against a general userspace library... that won't work at all in kernelspace.
Related
I am trying to compile a project using cmake. I need to use an external static library in src1.c so I utilized target_link_libraries to link it to the object file. However, I am getting some complains about missing functions in src1.c which should be in the external library.
add_library(input_output OBJECT
src/src1.c
src/src2.c
src/src3.c)
find_library(EXTERNAL_LIB NAMES libexternallib.a PATHS ~/lib)
target_link_libraries(input_output PRIVATE
"${EXTERNAL_LIB}")
So I am not sure what I should do at this point. the logic sounds right at least
UPDATE1: I also added the external library directly into the linker command
add_compile_options(-Wall -Wextra --std=c99 -L~/lib -lexternallib)
add_link_options(-L~/lib -lexternallib)
but this added the library flags before the object file for the linker command, which leads to some other problem with ordering the linker arguments
It's hard to say what is really the reason for your error here, but I'll give it a try.
First of all, you don't need to link manually with add_compile_options or add_link_options. The cmake command target_link_libraries is doing that for you.
What I could imagine, because of the missing functions, that you need to add a header include directory from the dependency.
e.g.:
target_include_directories(input_output PRIVATE /path/to/external_library_header)
I'm creating a makefile to build an existing project. We're using GNU Make 4, but the compiler doesn't automatically generate dependency information so I'm trying to determine the best way to specify dependencies for code that includes header files which in turn may include header files. Due to the complexity of the codebase, I think it will be unrealistic to traverse the entire #include tree, gather up all the header files, and then specify them for each source file.
One solution is to create makefile definitions of each header file and its direct dependencies, then create a recipe for a header file that touches that header file to trigger the recompile of the source that includes it:
a123.o: a123.c header1.h
header1.h: header2.h
header2.h: header3.h
# Recipes
%.o:
# compile command for building a .o
%.h:
#touch $#
This seems to work; if header3.h changes, then the %.h recipe updates header2.h's timestamp, which causes header1.h's timestamp to be updated, which causes a123.o to be rebuilt.
However, it seems messy, with all the touching, plus it seems odd to create a recipe for a source file that isn't directly compiled. Is this the correct way to do this sort of thing, or is there a cleaner approach? Please note that I simplified my question; in reality several languages are in use with different file extensions, the compiler isn't GCC, and the output isn't a .o file. But the logic is exactly the same.
I have a project where there's only a handful of logical groupings for generating static libraries. However for convenience I want to have the library's source code to be managed with more granular folders.
Currently the only way I know to do this in CMake without having a library for each folder is to just list files as you would normally in with their relative paths:
add_library(SystemAbstraction STATIC "Some/Path/File.cpp")
However I can see this getting unwieldy as the project grows in size with all the different paths.
I tried to see if I could have a CMakeLists.txt in each folder and just use a variable in the base CMakeLists.txt when adding library dependencies. But it seems that add_subdirectory doesn't also import variables?
For expanding the scope of a variable inside a subdirectory, use the PARENT_SCOPE option of set. For example, you can test that if you have
# CMakeLists.txt
set(SRCS main.c)
add_subdirectory(foo)
message(${SRCS})
in the root directory and
# foo/CMakeLists.txt
set(SRCS ${SRCS} foo.c PARENT_SCOPE)
in a subdirectory then it will print main.c foo.c, i.e., the variable is correctly imported into the base CMakeLists.txt.
An option would be to use the object library feature of CMake. You still can but doesn't need to organise your CMake script into subdirectories:
add_library(lib1 OBJECT <srcs>)
add_library(lib2 OBJECT <srcs>)
...
add_library(mainlib $<TARGET_OBJECTS:lib1> $<TARGET_OBJECTS:lib2>)
You can set different compile flags for each object library:
target_include_directories(lib1 PRIVATE incl-dir-for-lib1)
target_compile_definitions(lib2 PRIVATE def-for-lib2)
You still need to set link libraries on your main library:
target_link_libraries(mainlib PRIVATE deps-of-lib1 deps-of-lib2)
Related documentation: Object Libraries
I couldn't find any information regarding this in kbuild modules documentation and only an oblique reference (suggesting that it's possible) in the headers_install documentation.
The "make headers_install" command can be run in the top level directory of the
kernel source code (or using a standard out-of-tree build).
I have an out-of-tree kernel module with an associated header file (I have #defines for an IOCTL), and I want to provide that header file as part of the module installation. It seems like the in-tree way for kernel modules to provide header files (for userspace use) is to place them in include/linux/. What do I have to do for this to work for out-of-tree?
Ok, this seems to be another case where I didn't read all the manuals... the manual needed is the makefiles documentation for kbuild...
The kernel includes a set of headers that is exported to userspace.
Many headers can be exported as-is but other headers require a
minimal pre-processing before they are ready for user-space.
The pre-processing does:
drop kernel-specific annotations
drop include of compiler.h
drop all sections that are kernel internal (guarded by ifdef KERNEL)
Each relevant directory contains a file name "Kbuild" which specifies the
headers to be exported.
See subsequent chapter for the syntax of the Kbuild file.
--- 7.1 header-y
header-y specifies header files to be exported.
Example:
#include/linux/Kbuild
header-y += usb/
header-y += aio_abi.h
This seems to be deprecated. The headers_install target does not exist for out-of-tree module builds (see this answer).
Say there is a source file a.c with some function func_a. I would like to call func_a based on some feature define and would also like a.c to be included in the module based on ideally same feature define.
so in my module source that is always present (say main.c) I could have something like
#ifdef FEATURE_A
func_a();
#endif
and in the kbuild for the module something like
obj-$(CONFIG_SAMPLE) += sample.o
sample-objs := main.o utils.o
only if FEATURE_A is defined, include a.c into the sample module
???
But this may not make sense since one is a pre-processor directive and the other a compiler/linker/build directive. Maybe the other way where the pre-processor directive uses some flag defined by the kbuild makes more sense? Is there some way to accomplish this?
Thanks.
I will answer your question by pointing out how sysctl support is conditionally included in the NFS module (I'm sure there are other examples, but this is what I'm familiar with):
include/linux/nfs_fs.h
fs/nfs/Makefile
fs/nfs/super.c
The kernel config system maintains a file "include/linux/autoconf.h" that exposes your configuration options as C preprocessor macros. So the files listed above compile differently depending on whether you configured sysctl support.
If sysctl support is enabled: The header "include/linux/nfs_fs.h" checks the macro CONFIG_SYSCTL and declares the C function nfs_register_sysctl(). This function is called in "fs/nfs/super.c". The Makefile (seeing nfs-y += sysctl.o) directs the build system to compile in the file "fs/nfs/sysctl.c" into the module, which defines the function nfs_register_sysctl().
If sysctl support is disabled: The header "include/linux/nfs_fs.h" checks the macro CONFIG_SYSCTL and declares the preprocessor macro nfs_register_sysctl() to be 0. This macro is used in "fs/nfs/super.c" to bypass some (dead) error-handling code. The Makefile (seeing nfs-n += sysctl.o) does not compile or link "fs/nfs/sysctl.c".
Please read 3.7 Compilation flags.
As I understand it, there's loosless reletionship between Kconfig option and preprocessed macros, passed while compiling. It's up to kernel developer to define which preprocessor flags to use during compilation.
For example in net/rds/Makefile:
ccflags-$(CONFIG_RDS_DEBUG) := -DDEBUG
Here preprocessor flag DEBUG will be passed if you kernel is configured with Kconfig option CONFIG_RDS_DEBUG.