summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2016-03-01 00:48:24 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-03-02 23:08:51 +0000
commit5cf15ffecc4c1602190207870b8edf08d7bf8001 (patch)
tree92ac118edeb3bca6a5a2cf1f5531f2b752057afb
parent937ecd07d393ff3e543fb366b67876b498c9ac29 (diff)
downloadpoky-5cf15ffecc4c1602190207870b8edf08d7bf8001.tar.gz
recipetool: create: add support for out-of-tree kernel modules
Detect kernel modules by looking for #include <linux/module.h>, and handle the various styles of Makefile that appear to be used. I was able to use this code to successfully build a number of external kernel modules I found. Implements [YOCTO #8982]. (From OE-Core rev: a85604f2eb2438b4caf0832c2ea15b5822f7e9a1) Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--scripts/lib/recipetool/create_kmod.py152
1 files changed, 152 insertions, 0 deletions
diff --git a/scripts/lib/recipetool/create_kmod.py b/scripts/lib/recipetool/create_kmod.py
new file mode 100644
index 0000000000..fe39edb288
--- /dev/null
+++ b/scripts/lib/recipetool/create_kmod.py
@@ -0,0 +1,152 @@
1# Recipe creation tool - kernel module support plugin
2#
3# Copyright (C) 2016 Intel Corporation
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc.,
16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18import re
19import logging
20from recipetool.create import RecipeHandler, read_pkgconfig_provides, validate_pv
21
22logger = logging.getLogger('recipetool')
23
24tinfoil = None
25
26def tinfoil_init(instance):
27 global tinfoil
28 tinfoil = instance
29
30
31class KernelModuleRecipeHandler(RecipeHandler):
32 def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
33 import bb.process
34 if 'buildsystem' in handled:
35 return False
36
37 module_inc_re = re.compile(r'^#include\s+<linux/module.h>$')
38 makefiles = []
39 is_module = False
40
41 makefiles = []
42
43 files = RecipeHandler.checkfiles(srctree, ['*.c', '*.h'], recursive=True)
44 if files:
45 for cfile in files:
46 # Look in same dir or parent for Makefile
47 for makefile in [os.path.join(os.path.dirname(cfile), 'Makefile'), os.path.join(os.path.dirname(os.path.dirname(cfile)), 'Makefile')]:
48 if makefile in makefiles:
49 break
50 else:
51 if os.path.exists(makefile):
52 makefiles.append(makefile)
53 break
54 else:
55 continue
56 with open(cfile, 'r') as f:
57 for line in f:
58 if module_inc_re.match(line.strip()):
59 is_module = True
60 break
61 if is_module:
62 break
63
64 if is_module:
65 classes.append('module')
66 handled.append('buildsystem')
67 # module.bbclass and the classes it inherits do most of the hard
68 # work, but we need to tweak it slightly depending on what the
69 # Makefile does (and there is a range of those)
70 # Check the makefile for the appropriate install target
71 install_lines = []
72 compile_lines = []
73 in_install = False
74 in_compile = False
75 install_target = None
76 with open(makefile, 'r') as f:
77 for line in f:
78 if line.startswith('install:'):
79 if not install_lines:
80 in_install = True
81 install_target = 'install'
82 elif line.startswith('modules_install:'):
83 install_lines = []
84 in_install = True
85 install_target = 'modules_install'
86 elif line.startswith('modules:'):
87 compile_lines = []
88 in_compile = True
89 elif line.startswith(('all:', 'default:')):
90 if not compile_lines:
91 in_compile = True
92 elif line:
93 if line[0] == '\t':
94 if in_install:
95 install_lines.append(line)
96 elif in_compile:
97 compile_lines.append(line)
98 elif ':' in line:
99 in_install = False
100 in_compile = False
101
102 def check_target(lines, install):
103 kdirpath = ''
104 manual_install = False
105 for line in lines:
106 splitline = line.split()
107 if splitline[0] in ['make', 'gmake', '$(MAKE)']:
108 if '-C' in splitline:
109 idx = splitline.index('-C') + 1
110 if idx < len(splitline):
111 kdirpath = splitline[idx]
112 break
113 elif install and splitline[0] == 'install':
114 if '.ko' in line:
115 manual_install = True
116 return kdirpath, manual_install
117
118 kdirpath = None
119 manual_install = False
120 if install_lines:
121 kdirpath, manual_install = check_target(install_lines, install=True)
122 if compile_lines and not kdirpath:
123 kdirpath, _ = check_target(compile_lines, install=False)
124
125 if manual_install or not install_lines:
126 lines_after.append('EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"')
127 elif install_target and install_target != 'modules_install':
128 lines_after.append('MODULES_INSTALL_TARGET = "install"')
129
130 warnmsg = None
131 kdirvar = None
132 if kdirpath:
133 res = re.match(r'\$\(([^$)]+)\)', kdirpath)
134 if res:
135 kdirvar = res.group(1)
136 if kdirvar != 'KERNEL_SRC':
137 lines_after.append('EXTRA_OEMAKE += "%s=${STAGING_KERNEL_DIR}"' % kdirvar)
138 elif kdirpath.startswith('/lib/'):
139 warnmsg = 'Kernel path in install makefile is hardcoded - you will need to patch the makefile'
140 if not kdirvar and not warnmsg:
141 warnmsg = 'Unable to find means of passing kernel path into install makefile - if kernel path is hardcoded you will need to patch the makefile'
142 if warnmsg:
143 warnmsg += '. Note that the variable KERNEL_SRC will be passed in as the kernel source path.'
144 logger.warn(warnmsg)
145 lines_after.append('# %s' % warnmsg)
146
147 return True
148
149 return False
150
151def register_recipe_handlers(handlers):
152 handlers.append((KernelModuleRecipeHandler(), 15))