diff options
author | Bruce Ashfield <bruce.ashfield@gmail.com> | 2024-10-11 19:44:36 +0000 |
---|---|---|
committer | Bruce Ashfield <bruce.ashfield@gmail.com> | 2024-10-11 20:14:43 +0000 |
commit | dc37ea052ed74321c5244938f8d702372f663776 (patch) | |
tree | 5b561ff383ef5c358a181e99788aef9acd00ef29 | |
parent | 4f7788bbebe80f1c6b13bd3bc2db875e900bfa29 (diff) | |
download | meta-cloud-services-dc37ea052ed74321c5244938f8d702372f663776.tar.gz |
ruby/rubyv2: add new rubyv2 bbclass and support external extconf
When building/installing gems with native components, the target
OS and cross compile settings were not correctly being picked up.
Enhance the existing bbclass with the ability to copy a extconf.rb
from UNPACKDIR, so a recipe can specify fixes in it's own copy of
the file.
We also bring in a class from meta-rubygems which has more advanced
cross compile settings. There are a few minor modifications to
this class (copying of extconf.rb) and some spec generation. But
it is now available if the basic ruby class cannot compile and install
a gem.
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
-rw-r--r-- | classes/ruby.bbclass | 27 | ||||
-rw-r--r-- | classes/rubyv2.bbclass | 322 | ||||
-rw-r--r-- | recipes-support/puppet/puppet_7.33.0.bb (renamed from recipes-support/puppet/puppet_5.4.0.bb) | 0 |
3 files changed, 347 insertions, 2 deletions
diff --git a/classes/ruby.bbclass b/classes/ruby.bbclass index 384ece9..eb19e37 100644 --- a/classes/ruby.bbclass +++ b/classes/ruby.bbclass | |||
@@ -1,5 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2014 Wind River Systems, Inc. | 2 | # Copyright (C) 2014 Wind River Systems, Inc. |
3 | # Copyright (c) 2024 Bruce Ashfield, Inc. | ||
3 | # | 4 | # |
4 | DEPENDS += " \ | 5 | DEPENDS += " \ |
5 | ruby-native \ | 6 | ruby-native \ |
@@ -24,7 +25,7 @@ def get_rubyversion(p): | |||
24 | return found_version | 25 | return found_version |
25 | 26 | ||
26 | version = subprocess.Popen([cmd, "--version"], stdout=subprocess.PIPE).communicate()[0] | 27 | version = subprocess.Popen([cmd, "--version"], stdout=subprocess.PIPE).communicate()[0] |
27 | 28 | ||
28 | r = re.compile("ruby ([0-9]+\.[0-9]+\.[0-9]+)*") | 29 | r = re.compile("ruby ([0-9]+\.[0-9]+\.[0-9]+)*") |
29 | m = r.match(version) | 30 | m = r.match(version) |
30 | if m: | 31 | if m: |
@@ -66,7 +67,7 @@ def get_rubygemsversion(p): | |||
66 | return found_version | 67 | return found_version |
67 | 68 | ||
68 | version = subprocess.Popen([cmd, "env", "gemdir"], stdout=subprocess.PIPE).communicate()[0] | 69 | version = subprocess.Popen([cmd, "env", "gemdir"], stdout=subprocess.PIPE).communicate()[0] |
69 | 70 | ||
70 | r = re.compile(".*([0-9]+\.[0-9]+\.[0-9]+)$") | 71 | r = re.compile(".*([0-9]+\.[0-9]+\.[0-9]+)$") |
71 | m = r.match(version.decode("utf-8")) | 72 | m = r.match(version.decode("utf-8")) |
72 | if m: | 73 | if m: |
@@ -108,6 +109,11 @@ EOF | |||
108 | } | 109 | } |
109 | 110 | ||
110 | ruby_do_compile() { | 111 | ruby_do_compile() { |
112 | if [ -f ${UNPACKDIR}/extconf.rb ]; then | ||
113 | cp extconf.rb extconf.orig | ||
114 | cp ${UNPACKDIR}/extconf.rb extconf.rb | ||
115 | fi | ||
116 | |||
111 | if [ -f extconf.rb -a ! -f extconf.rb.orig ] ; then | 117 | if [ -f extconf.rb -a ! -f extconf.rb.orig ] ; then |
112 | grep create_makefile extconf.rb > append2 || (exit 0) | 118 | grep create_makefile extconf.rb > append2 || (exit 0) |
113 | ruby_gen_extconf_fix | 119 | ruby_gen_extconf_fix |
@@ -164,3 +170,20 @@ FILES:${PN} += " \ | |||
164 | FILES:${PN}-doc += " \ | 170 | FILES:${PN}-doc += " \ |
165 | ${libdir}/ruby/gems/${RUBY_GEM_VERSION}/doc \ | 171 | ${libdir}/ruby/gems/${RUBY_GEM_VERSION}/doc \ |
166 | " | 172 | " |
173 | |||
174 | # copied from rubyv2.bbclass | ||
175 | |||
176 | # the ruby dynamic linker just uses plain .so files | ||
177 | # so we have to supply symlinks as part of the base package | ||
178 | INSANE_SKIP:${PN} += "dev-so" | ||
179 | # sadly the shared objects also contain some hard coded | ||
180 | # host paths, which are not easy to be removed | ||
181 | INSANE_SKIP:${PN} += "buildpaths" | ||
182 | # we don't care what is actually needed for the dev-package | ||
183 | INSANE_SKIP:${PN}-dev += "file-rdeps" | ||
184 | # same issue for the dev package with buildpaths | ||
185 | INSANE_SKIP:${PN}-dev += "buildpaths" | ||
186 | # some of the doc utils contain host specific full paths | ||
187 | # as they are mostly in binary format we are just going to | ||
188 | # ignore it here | ||
189 | INSANE_SKIP:${PN}-doc += "buildpaths" | ||
diff --git a/classes/rubyv2.bbclass b/classes/rubyv2.bbclass new file mode 100644 index 0000000..3d6654e --- /dev/null +++ b/classes/rubyv2.bbclass | |||
@@ -0,0 +1,322 @@ | |||
1 | # copied from: https://layers.openembedded.org/layerindex/branch/master/layer/meta-rubygems/ | ||
2 | # | ||
3 | # - One local modifcation was made to copy an extconf.rb from UNPACKDIR to the | ||
4 | # build. | ||
5 | # - This copy will eventually be deleted, once factoring happens between the | ||
6 | # two classes. | ||
7 | |||
8 | ## SPDX-License-Identifier: MIT, BSD-2-Clause | ||
9 | ## Copyright (c) 2015, Michaƫl Burtin | ||
10 | ## Copyright (c) 2020, Konrad Weihmann | ||
11 | |||
12 | GEMLIB_VERSION = "3.3.0" | ||
13 | |||
14 | GEM_SRC ?= "https://rubygems.org/gems" | ||
15 | |||
16 | # Enforce IPv4 connection - IPv6 seems to be broken | ||
17 | # nooelint: oelint.vars.specific,oelint.vars.pathhardcode.bindir | ||
18 | # FETCHCMD_wget ?= "/usr/bin/env wget -t 2 -T 30 --passive-ftp -4" | ||
19 | |||
20 | GEM_NAME ?= "" | ||
21 | GEM_VERSION ?= "${PV}" | ||
22 | |||
23 | # SRC_URI = "${GEM_SRC}/${GEM_FILENAME}" | ||
24 | GEMPREFIX = "gem-" | ||
25 | |||
26 | UNPACKDIR ??= "${WORKDIR}/gem-dl" | ||
27 | |||
28 | # S = "${UNPACKDIR}/${GEM_NAME}-${GEM_VERSION}" | ||
29 | |||
30 | GEM_FILENAME = "${GEM_NAME}-${GEM_VERSION}.gem" | ||
31 | GEM_FILE ?= "${UNPACKDIR}/${GEM_FILENAME}" | ||
32 | GEM_BUILT_FILE = "${UNPACKDIR}/${GEM_FILENAME}" | ||
33 | |||
34 | GEM_SPEC_FILENAME = "${GEM_FILENAME}spec" | ||
35 | GEM_SPEC_FILE ?= "${S}/${GEM_SPEC_FILENAME}" | ||
36 | GEM_SPEC_CACHE ?= "${T}/.gems" | ||
37 | |||
38 | GEM_DIR = "${libdir}/ruby/gems/${GEMLIB_VERSION}" | ||
39 | RUBY_SITEDIR = "${libdir}/ruby/site_ruby/" | ||
40 | GEM_HOME = "${D}${GEM_DIR}" | ||
41 | GEM_PATH:class-target = "${RECIPE_SYSROOT}${GEM_DIR}:${RECIPE_SYSROOT}${GEM_DIR}:${GEM_HOME}" | ||
42 | GEM_PATH:class-native = "${RECIPE_SYSROOT_NATIVE}${GEM_DIR}:${GEM_HOME}" | ||
43 | |||
44 | # Disable the very strict versioning with ~> | ||
45 | GEM_DISABLE_STRICT_VER ?= "1" | ||
46 | |||
47 | GEM_INSTALL_FLAGS ?= "" | ||
48 | |||
49 | # Use the following to define extra depend/rdepends | ||
50 | # which cannot be seen by the package updater | ||
51 | EXTRA_RDEPENDS ?= "" | ||
52 | EXTRA_DEPENDS ?= "" | ||
53 | |||
54 | RUBYLIB_EXTRA_PATHS ?= "" | ||
55 | |||
56 | def extra_paths(d): | ||
57 | res = (d.getVar('RUBYLIB_EXTRA_PATHS') or '').split(' ') | ||
58 | if res: | ||
59 | return ':' + ':'.join(res) | ||
60 | return '' | ||
61 | |||
62 | RUBYLIB:class-target = "${STAGING_LIBDIR_NATIVE}/ruby/${GEMLIB_VERSION}/${@get_build_platform_folder(d)}${@extra_paths(d)}" | ||
63 | RUBYPLATFORM ?= "ruby" | ||
64 | RUBYPLATFORM:class-target ?= "${@get_target_platform_folder(d)}" | ||
65 | CFLAGS:append = " -DHAVE_GCC_CAS" | ||
66 | |||
67 | def get_gem_name_from_bpn(d): | ||
68 | bpn = (d.getVar('BPN', True) or "") | ||
69 | gemPrefix = (d.getVar('GEMPREFIX', True) or "") | ||
70 | if bpn.startswith(gemPrefix): | ||
71 | gemName = bpn[len(gemPrefix):] | ||
72 | else: | ||
73 | gemName = bpn | ||
74 | return gemName | ||
75 | |||
76 | def get_build_platform_folder(d): | ||
77 | build_arch = d.getVar("BUILD_ARCH") | ||
78 | build_os = d.getVar("BUILD_OS") | ||
79 | if build_os.endswith("linux"): | ||
80 | build_os = build_os.replace('linux', 'linux-gnu') | ||
81 | return build_arch + "-" + build_os | ||
82 | |||
83 | def get_target_platform_folder(d): | ||
84 | target_arch = d.getVar("HOST_ARCH") | ||
85 | target_os = d.getVar("HOST_OS") | ||
86 | if target_os.endswith("linux"): | ||
87 | target_os = target_os.replace('linux', 'linux-gnu') | ||
88 | return target_arch + "-" + target_os | ||
89 | |||
90 | do_gem_unpack() { | ||
91 | return | ||
92 | |||
93 | export RUBYLIB=${RUBYLIB} | ||
94 | |||
95 | cd ${UNPACKDIR} | ||
96 | # GEM_FILE might not exist if SRC_URI was overloaded | ||
97 | [ ! -e ${GEM_FILE} ] && return 0 | ||
98 | |||
99 | gem unpack -V ${GEM_FILE} | ||
100 | } | ||
101 | |||
102 | DEPENDS:append = " ruby-native ${EXTRA_DEPENDS}" | ||
103 | DEPENDS:append:class-target = " ruby ruby-native ${EXTRA_DEPENDS}" | ||
104 | |||
105 | python () { | ||
106 | d.appendVarFlag('do_gem_unpack', 'depends', ' ruby-native:do_populate_sysroot') | ||
107 | } | ||
108 | |||
109 | do_gem_unpack[vardepsexclude] += "prefix_native" | ||
110 | addtask do_gem_unpack after do_unpack before do_patch | ||
111 | |||
112 | python do_unpack:append() { | ||
113 | # as the actual unpack happens in do_gem_unpack | ||
114 | # we will work around insane-class checks | ||
115 | # by just creating the needed directories here | ||
116 | os.makedirs(d.expand('${S}'), exist_ok=True) | ||
117 | os.makedirs(d.expand('${UNPACKDIR}'), exist_ok=True) | ||
118 | } | ||
119 | |||
120 | do_generate_spec() { | ||
121 | export RUBYLIB=${RUBYLIB} | ||
122 | export GEM_SPEC=${GEM_SPEC_CACHE} | ||
123 | |||
124 | # GEM_FILE might not exist if SRC_URI was overloaded | ||
125 | [ ! -e ${GEM_FILE} ] && return 0 | ||
126 | |||
127 | gem spec -V --ruby ${GEM_FILE} > ${GEM_SPEC_FILE} | ||
128 | |||
129 | # lift the version bindings to be less strict | ||
130 | if [ "${GEM_DISABLE_STRICT_VER}" -eq "1" ]; then | ||
131 | sed -i 's#=[[:space:]]*[0-9]\+\.[0-9]\+#!=0#g' ${GEM_SPEC_FILE} | ||
132 | sed -i 's#~>#>=#g' ${GEM_SPEC_FILE} | ||
133 | sed -i 's#<=[[:space:]]*[0-9]\+\.[0-9]\+\.[0-9]\+#!=0#g' ${GEM_SPEC_FILE} | ||
134 | sed -i 's#<[[:space:]]*[0-9]\+\.[0-9]\+\.[0-9]\+#!=0#g' ${GEM_SPEC_FILE} | ||
135 | sed -i 's#<[[:space:]]*[0-9]\+\.[0-9]\+#!=0#g' ${GEM_SPEC_FILE} | ||
136 | sed -i 's#>!=#!=#g' ${GEM_SPEC_FILE} | ||
137 | sed -i 's#!!=#!=#g' ${GEM_SPEC_FILE} | ||
138 | sed -i 's#<!=0#!=0#g' ${GEM_SPEC_FILE} | ||
139 | fi | ||
140 | } | ||
141 | |||
142 | do_generate_spec[vardepsexclude] += "prefix_native" | ||
143 | addtask do_generate_spec after do_gem_unpack before do_patch | ||
144 | |||
145 | python do_arch_patch_config() { | ||
146 | import re | ||
147 | if bb.data.inherits_class('native', d): | ||
148 | return | ||
149 | target_cpu, target_vendor, target_os = get_target_platform_folder(d).split('-') | ||
150 | |||
151 | _map = { | ||
152 | "AR": d.expand("${AR}"), | ||
153 | "arch": d.expand("${RUBYPLATFORM}"), | ||
154 | "archincludedir": "$(includedir)", | ||
155 | "archlibdir": "$(libdir)", | ||
156 | "AS": d.expand("${AS}"), | ||
157 | "CC": d.expand("${CC}"), | ||
158 | "CFLAGS": d.expand("${CFLAGS}"), | ||
159 | "CPP": d.expand("${CPP}"), | ||
160 | "CPPFLAGS": d.expand("${CPPFLAGS}"), | ||
161 | "cppflags": d.expand("${CPPFLAGS}"), | ||
162 | "CROSS_COMPILING": "yes", | ||
163 | "CXX": d.expand("${CXX}"), | ||
164 | "CXXFLAGS": d.expand("${CFLAGS}"), | ||
165 | "DLEXT": d.expand("so.${PV}"), | ||
166 | "host_alias": "-".join([target_cpu, target_vendor]), | ||
167 | "host_cpu": target_cpu, | ||
168 | "host_os": target_os, | ||
169 | "host": get_target_platform_folder(d), | ||
170 | "includedir": d.expand("${STAGING_INCDIR}"), | ||
171 | "LD": d.expand("${LD}"), | ||
172 | "LDFLAGS": d.expand("${LDFLAGS}"), | ||
173 | "libdir": d.getVar("STAGING_LIBDIR"), | ||
174 | "libexecdir": "$(exec_prefix)/libexec", | ||
175 | "NM": d.expand("${NM}"), | ||
176 | "OBJDUMP": d.expand("${OBJDUMP}"), | ||
177 | "RANLIB": d.expand("${RANLIB}"), | ||
178 | "SOEXT": d.expand("so.${PV}"), | ||
179 | "STRIP": d.expand("${STRIP}"), | ||
180 | "target_alias": "-".join([target_cpu, target_vendor]), | ||
181 | "target_cpu": target_cpu, | ||
182 | "target_os": target_os, | ||
183 | "target": get_target_platform_folder(d), | ||
184 | "TEST_RUNNABLE": "no", | ||
185 | #"DLDFLAGS": d.expand("${LDFLAGS}"), | ||
186 | } | ||
187 | |||
188 | cnt = "" | ||
189 | for item in d.expand("${RUBYLIB}").split(':'): | ||
190 | item = os.path.join(item, 'rbconfig.rb') | ||
191 | if not os.path.isfile(item) or not os.path.exists(item): | ||
192 | continue | ||
193 | with open(item) as i: | ||
194 | cnt = i.read() | ||
195 | |||
196 | for m in re.finditer(r'^(\s+|\t+)CONFIG\[\"(?P<var>.*)\"\]\s+=\s+\"(?P<value>.*)\"$', cnt, re.MULTILINE): | ||
197 | if m.group("var") in _map: | ||
198 | _rpl = ' CONFIG["{}"] = "{}"'.format(m.group("var"), _map[m.group("var")]) | ||
199 | bb.note("Replace {} by {}".format(m.group(0), _rpl)) | ||
200 | cnt = cnt.replace(m.group(0), _rpl) | ||
201 | |||
202 | with open(item, "w") as o: | ||
203 | o.write(cnt) | ||
204 | } | ||
205 | |||
206 | do_arch_patch_config[doc] = "patches the correct compiler settings into the cross template" | ||
207 | addtask do_arch_patch_config after do_generate_spec do_gem_unpack before do_compile | ||
208 | |||
209 | rubyv2_do_compile() { | ||
210 | export GEM_PATH=${GEM_PATH} | ||
211 | export GEM_HOME=${GEM_HOME} | ||
212 | export GEM_SPEC=${GEM_SPEC_CACHE} | ||
213 | export RUBYLIB=${RUBYLIB} | ||
214 | |||
215 | export LANG="en_US.UTF-8" | ||
216 | export LANGUAGE="en_US.UTF-8" | ||
217 | export LC_ALL="en_US.UTF-8" | ||
218 | |||
219 | if [ -f ${UNPACKDIR}/extconf.rb ]; then | ||
220 | cp extconf.rb extconf.orig | ||
221 | cp ${UNPACKDIR}/extconf.rb extconf.rb | ||
222 | fi | ||
223 | |||
224 | # Older versions of gem build don't understand -o flag, so try it once more without | ||
225 | # it, if the command is failing | ||
226 | gem build -V ${GEM_SPEC_FILE} -o ${GEM_BUILT_FILE} || gem build -V ${GEM_SPEC_FILE} | ||
227 | |||
228 | # for the install step | ||
229 | do_generate_spec | ||
230 | } | ||
231 | |||
232 | python do_rubyv2_fix_libs() { | ||
233 | # as ruby dynloader expects the shared .so files | ||
234 | # without extension we will create symlinks to the | ||
235 | # properly versioned file | ||
236 | for root, dirs, files in os.walk(d.expand("${GEM_HOME}")): | ||
237 | for f in files: | ||
238 | if f.endswith(d.expand("so.${PV}")): | ||
239 | _filename = os.path.basename(f) | ||
240 | while "." in _filename: | ||
241 | try: | ||
242 | os.symlink(os.path.basename(f), os.path.join(root, _filename)) | ||
243 | except: | ||
244 | pass | ||
245 | _filename, _ = os.path.splitext(_filename) | ||
246 | } | ||
247 | |||
248 | RUBY_INSTALL_EXTRA_FLAGS ?= "" | ||
249 | |||
250 | rubyv2_do_install() { | ||
251 | export GEM_PATH=${GEM_PATH} | ||
252 | export GEM_SPEC=${GEM_SPEC_CACHE} | ||
253 | export RUBYLIB=${RUBYLIB} | ||
254 | |||
255 | gem uninstall ${GEM_NAME} --version ${GEM_VERSION} -x -q -V || true | ||
256 | |||
257 | gem install --local --bindir ${D}${bindir} ${GEM_BUILT_FILE} --install-dir=${GEM_HOME} -E --backtrace --norc --no-user-install --ignore-dependencies --force --conservative -V ${RUBY_INSTALL_EXTRA_FLAGS} -- ${GEM_INSTALL_FLAGS} | ||
258 | |||
259 | # remove all object files | ||
260 | find ${GEM_HOME} -name "*.o" -type f -exec rm -f {} \; | ||
261 | } | ||
262 | |||
263 | EXPORT_FUNCTIONS do_compile do_install | ||
264 | do_install[postfuncs] += "do_rubyv2_fix_libs" | ||
265 | |||
266 | PACKAGES =+ "${PN}-examples ${PN}-tests" | ||
267 | |||
268 | FILES:${PN}-dbg += "\ | ||
269 | /usr/src/debug/* \ | ||
270 | ${libdir}/ruby/**/.debug \ | ||
271 | " | ||
272 | FILES:${PN}-staticdev += "\ | ||
273 | ${libdir}/ruby/gems/gems/**/.libs/*.a \ | ||
274 | " | ||
275 | FILES:${PN}-dev += "\ | ||
276 | ${GEM_DIR}/extensions/*/*/*/gem_make.out \ | ||
277 | ${GEM_DIR}/extensions/*/*/*/mkmf.log \ | ||
278 | ${GEM_DIR}/build_info \ | ||
279 | ${GEM_DIR}/cache \ | ||
280 | ${GEM_DIR}/gems/*/debian.template \ | ||
281 | ${GEM_DIR}/gems/*/ext/ \ | ||
282 | ${GEM_DIR}/gems/*/spec/ \ | ||
283 | ${GEM_DIR}/gems/*/lib/generators \ | ||
284 | ${GEM_DIR}/gems/*/patches \ | ||
285 | " | ||
286 | FILES:${PN}-tests = "\ | ||
287 | ${GEM_DIR}/gems/*/tests \ | ||
288 | ${GEM_DIR}/gems/*/test \ | ||
289 | " | ||
290 | FILES:${PN}-examples = "\ | ||
291 | ${GEM_DIR}/gems/*/example \ | ||
292 | ${GEM_DIR}/gems/*/samples \ | ||
293 | " | ||
294 | FILES:${PN}-doc += "\ | ||
295 | ${GEM_DIR}/gems/*/doc \ | ||
296 | ${GEM_DIR}/doc \ | ||
297 | " | ||
298 | FILES:${PN} += "\ | ||
299 | ${GEM_DIR}/extensions \ | ||
300 | ${GEM_DIR}/gems \ | ||
301 | ${GEM_DIR}/specifications \ | ||
302 | ${RUBY_SITEDIR} \ | ||
303 | ${libdir}/ruby/gems/${GEMLIB_VERSION}/plugins \ | ||
304 | " | ||
305 | |||
306 | RDEPENDS:${PN}:append:class-target = " ruby ${EXTRA_RDEPENDS}" | ||
307 | RDEPENDS:${PN}-tests:append:class-target = " ruby" | ||
308 | |||
309 | # the ruby dynamic linker just uses plain .so files | ||
310 | # so we have to supply symlinks as part of the base package | ||
311 | INSANE_SKIP:${PN} += "dev-so" | ||
312 | # sadly the shared objects also contain some hard coded | ||
313 | # host paths, which are not easy to be removed | ||
314 | INSANE_SKIP:${PN} += "buildpaths" | ||
315 | # we don't care what is actually needed for the dev-package | ||
316 | INSANE_SKIP:${PN}-dev += "file-rdeps" | ||
317 | # same issue for the dev package with buildpaths | ||
318 | INSANE_SKIP:${PN}-dev += "buildpaths" | ||
319 | # some of the doc utils contain host specific full paths | ||
320 | # as they are mostly in binary format we are just going to | ||
321 | # ignore it here | ||
322 | INSANE_SKIP:${PN}-doc += "buildpaths" | ||
diff --git a/recipes-support/puppet/puppet_5.4.0.bb b/recipes-support/puppet/puppet_7.33.0.bb index c207e40..c207e40 100644 --- a/recipes-support/puppet/puppet_5.4.0.bb +++ b/recipes-support/puppet/puppet_7.33.0.bb | |||