[英]Yocto/ Bitbake - incorporate build version (e.g. PE, PR & PV) into C++ compilation
I've done a bit of searching but can't find an answer to this issue.我做了一些搜索,但找不到这个问题的答案。
I have a C++ GUI application that is built using Autotools in a Yocto/ Poky image.我有一个 C++ GUI 应用程序,它是在 Yocto/Poky 图像中使用 Autotools 构建的。 The PR service has been enabled & for issue tracking I'd like to incorporate the build version of the C++ application into the GUI (so the user can see it's v 0.9.1002 or similar on the GUI).
PR 服务已启用并用于问题跟踪我想将 C++ 应用程序的构建版本合并到 GUI 中(以便用户可以在 GUI 上看到它的 v 0.9.1002 或类似版本)。
Is there a way of accomplishing this with a recipe or so I need to amend the Autotools files to build in the build version somehow?有没有办法通过配方来完成这个,或者我需要修改 Autotools 文件以某种方式构建构建版本?
Thanks for looking,感谢您的关注,
Edit: Thanks for the responses.编辑:感谢您的回复。
The project I put together (based on the the EGT framework) is fairly big & pulled from my repo in github with Yocto/ Bitbake.我放在一起的项目(基于EGT框架)相当大,并且是从我在 github 的存储库中使用 Yocto/Bitbake 提取的。 PV & PE I'll increment as necessary & the PR generation is supplied by Bitbake.
PV & PE 我将根据需要增加, PR 生成由 Bitbake 提供。 A MRE is something like:
MRE 类似于:
#include <egt/ui>
extern char __build_ver // Ideally supplied by Bitbake/ Autotools
int main(int argc, char** argv)
{
egt::Application app(argc, argv);
egt::TopWindow window;
egt::Label label(window, __build_ver);
egt::center(label);
window.show();
return app.run();
}
And the configure.ac is similar to: configure.ac类似于:
AC_PREREQ([2.69])
AC_INIT([egt-demo],[1.3])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_MACRO_DIR([m4])
AC_USE_SYSTEM_EXTENSIONS
AC_CANONICAL_TARGET
PKG_PROG_PKG_CONFIG
AM_INIT_AUTOMAKE([1.10 foreign subdir-objects])
# Enable quiet compiles on automake 1.11.
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Initialize libtool
LT_PREREQ([2.2])
LT_INIT([win32-dll])
AC_LANG(C++)
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX([14], [noext])
AC_PROG_CC
AC_PROG_CPP
AC_CHECK_HEADER_STDBOOL
AC_C_INLINE
AC_TYPE_UINT32_T
AX_PTHREAD([LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"],
AC_MSG_ERROR(Can not find pthreads. This is required.))
AC_DEFUN([EGT_CC_TRY_FLAG], [
AC_MSG_CHECKING([whether $CC supports $1])
egt_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1 -Werror"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([ ])], [egt_cc_flag=yes], [egt_cc_flag=no])
CFLAGS="$egt_save_CFLAGS"
if test "x$egt_cc_flag" = "xyes"; then
ifelse([$2], , :, [$2])
else
ifelse([$3], , :, [$3])
fi
AC_MSG_RESULT([$egt_cc_flag])
])
MAYBE_WARN="-Wall -Wextra \
-pedantic \
-Wfloat-equal \
-Wsign-compare \
-Wpointer-arith \
-Wwrite-strings \
-Wmissing-declarations \
-Wpacked \
-Wstrict-aliasing=2 -Winit-self \
-Wno-attributes -Wno-long-long \
-Wno-missing-field-initializers \
-Wno-unused-parameter \
-Wno-psabi" # no warnings about gcc abi changes
# invalidate cached value if MAYBE_WARN has changed
if test "x$egt_cv_warn_maybe" != "x$MAYBE_WARN"; then
unset egt_cv_warn_cflags
fi
AC_CACHE_CHECK([for supported warning flags], egt_cv_warn_cflags, [
echo
WARN_CFLAGS=""
# Some warning options are not supported by all versions of
# gcc, so test all desired options against the current
# compiler.
#
# Note that there are some order dependencies
# here. Specifically, an option that disables a warning will
# have no net effect if a later option then enables that
# warnings, (perhaps implicitly). So we put some grouped
# options (-Wall and -Wextra) up front and the -Wno options
# last.
for W in $MAYBE_WARN; do
EGT_CC_TRY_FLAG([$W], [WARN_CFLAGS="$WARN_CFLAGS $W"])
done
egt_cv_warn_cflags=$WARN_CFLAGS
egt_cv_warn_maybe=$MAYBE_WARN
AC_MSG_CHECKING([which warning flags were supported])])
WARN_CFLAGS="$egt_cv_warn_cflags"
AC_SUBST(WARN_CFLAGS)
AC_DEFUN([LIBINTL_SRC], [
AC_LANG_PROGRAM([[
#include <libintl.h>
]],[[
char *msg = gettext("test");
]])])
AC_MSG_CHECKING([if libc contains libintl])
AC_LINK_IFELSE([LIBINTL_SRC],
[AC_MSG_RESULT([yes])
LIBC_CONTAINS_LIBINTL=Yes],
[AC_MSG_RESULT([no])
LIBC_CONTAINS_LIBINTL=])
AC_SUBST([LIBC_CONTAINS_LIBINTL])
AC_CHECK_HEADER([libintl.h],
[NO_GETTEXT=],
[NO_GETTEXT=Yes])
AC_SUBST([NO_GETTEXT])
if test -z "$NO_GETTEXT"; then
test -n "$LIBC_CONTAINS_LIBINTL" || LIBS="$LIBS -lintl"
fi
PKG_CHECK_MODULES(LIBEGT, [libegt >= 1.3], [], [
AC_MSG_ERROR(libegt not found. This is required.)
])
AC_ARG_WITH([sensors],
AS_HELP_STRING([--without-sensors], [Ignore presence of sensors and disable it]))
AS_IF([test "x$with_sensors" != "xno"],[
AC_CHECK_HEADER([sensors/sensors.h], [have_sensors=yes], [have_sensors=no])
if test "x${have_sensors}" = xyes; then
CXXFLAGS="-DLUA_USE_READLINE ${CXXFLAGS}"
LDFLAGS="-lsensors ${LDFLAGS}"
AC_DEFINE(HAVE_SENSORS, 1, [Have sensors support])
fi
])
AM_CONDITIONAL([HAVE_SENSORS], [test "x${have_sensors}" = xyes])
AC_ARG_ENABLE([lto],
[AS_HELP_STRING([--enable-lto], [enable gcc's LTO [default=no]])],
[enable_lto=$enableval], [enable_lto=no])
if test "x$enable_lto" = "xyes" ; then
AC_MSG_NOTICE([enabling LTO])
CFLAGS="$CFLAGS -flto"
CXXFLAGS="$CXXFLAGS -flto"
fi
AC_CONFIG_FILES([Makefile external/Makefile])
AC_OUTPUT
My Bitbake recipe is:我的 Bitbake 食谱是:
DESCRIPTION = "XXX Application"
LICENSE = "CLOSED"
PACKAGES = "\
${PN} \
${PN}-dev \
${PN}-dbg \
"
# PR service enabled in local.conf
SRC_URI = "git://git@github.com/xxxxx/xxxxxxxxxxx.git;protocol=ssh;branch=main"
SRCREV="${AUTOREV}"
PV = "1.0+git${SRCPV}"
S = "${WORKDIR}/git"
# out-of-tree building doesn't appear to work for this package.
B = "${S}"
inherit pkgconfig autotools gettext
do_configure_prepend() {
( cd ${S};
${S}/autogen.sh; cd -)
}
FILES_${PN} += " \
${datadir}/xxxxxx/* \
"
python __anonymous () {
endianness = d.getVar('SITEINFO_ENDIANNESS')
if endianness == 'be':
raise bb.parse.SkipRecipe('Requires little-endian target.')
}
I am still not sure I completely understand your problem and its environment (I am completely unfamiliar with bitbake and yocto), but the following will show the package version number as an egt::Label
, and even allow the packaging scripts calling configure
and make
to add more version information.我仍然不确定我是否完全理解您的问题及其环境(我对 bitbake 和 yocto 完全不熟悉),但以下将显示包版本号为
egt::Label
,甚至允许调用configure
和make
的打包脚本添加更多版本信息。 HTH. HTH。
#include "config.h"
#include <egt/ui>
char build_version_string[] =
PACKAGE_VERSION
#ifdef ADDITIONAL_VERSION_STR
" (" ADDITIONAL_VERSION_STR ")"
#endif
;
int main(int argc, char** argv)
{
egt::Application app(argc, argv);
egt::TopWindow window;
egt::Label label(window, build_version_string);
This should make the label show the "1.3"
version string from the second argument to AC_INIT()
.这应该使标签显示来自
AC_INIT()
的第二个参数的"1.3"
版本字符串。
And if you want to add additional version information, you can define the ADDITIONAL_VERSION_STR
macro when your yocto/bitbake/whatever script/recipe/whatever build the package:如果你想添加额外的版本信息,你可以在你的 yocto/bitbake/whatever script/recipe/whatever 构建包时定义
ADDITIONAL_VERSION_STR
宏:
PR=1002
more_version_info="yocto foobar $PR"
tar xf egt-demo-1.3.tar.gz
cd egt-demo-1.3
./configure CPPFLAGS="-DADDITIONAL_VERSION_STR=\"${more_version_info}\"" --prefix=...
make
make install
This should make the label show "1.3 (yocto foobar 1002)"
.这应该使标签显示
"1.3 (yocto foobar 1002)"
。
Some remarks, in more or less decreasing order of actually being related to the question:一些评论,实际上与问题相关的或多或少的递减顺序:
grep PACKAGE_ config.h
might reveal more interesting information, especially if you read https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Initializing-configure.html and use more than two arguments to AC_INIT
. grep PACKAGE_ config.h
可能会揭示更多有趣的信息,特别是如果您阅读https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Initializing-configure.html并使用两个以上AC_INIT
参数.
It can be useful to put the char build_version_string[]
into its separate compilation unit (C or C++) like build-version.c
with a corresponding build-version.h
, as this can help avoid potentially expensive rebuilds of a potentially large main.cc
file due to changes in config.h
.将
char build_version_string[]
放入其单独的编译单元(C 或 C++)中会很有用,例如带有相应 build- build-version.c
的build-version.h
,因为这可以帮助避免对潜在的大型main.cc
文件由于config.h
的变化。
This avoids macros or symbols starting with _
or __
, as those usually are reserved by C or C++ language standards.这避免了以
_
或__
开头的宏或符号,因为它们通常由 C 或 C++ 语言标准保留。
If configure
calls macros not shipped by Autoconf or Automake, I recommend to explicitly m4_pattern_forbid
them.如果
configure
调用 Autoconf 或 Automake 未提供的宏,我建议明确地m4_pattern_forbid
它们。 This will make autoreconf
runs fail early, if any of the necessary m4 macros cannot be found and therefore unexpanded macro invocations like PKG_*
or LT_*
or AX_*
might appear in the generated configure
script:如果找不到任何必要的 m4 宏,这将使
autoreconf
运行提前失败,因此未扩展的宏调用(如PKG_*
或LT_*
或AX_*
可能会出现在生成的configure
脚本中:
m4_pattern_forbid([PKG_PROG_PKG_CONFIG]) PKG_PROG_PKG_CONFIG
The Autoconf release 2.69 you require was released 2012-04-25.您需要的 Autoconf 版本 2.69 于 2012 年 4 月 25 日发布。 The Automake release 1.10 you require was released 2006-10-15.
您需要的 Automake 版本 1.10 于 2006 年 10 月 15 日发布。 The Automake release 1.11 which introduced the
silent-rules
option to AM_INIT_AUTOMAKE
and the AM_SILENT_RULES
macro was released 2009-05-17. Automake 1.11 版向
AM_INIT_AUTOMAKE
和AM_SILENT_RULES
宏引入了silent-rules
选项,于 2009 年 5 月 17 日发布。 So you can reasonably presume that any system with autoconf 2.69 will probably have an automake version which is less than three years older, and remove the conditional around AM_SILENT_RULES
and just use因此,您可以合理地假设任何具有 autoconf 2.69 的系统都可能具有不到三年的 automake 版本,并删除
AM_SILENT_RULES
周围的条件并使用
AM_INIT_AUTOMAKE([ 1.11 foreign subdir-objects ]) AM_SILENT_RULES([yes])
or或者
AM_INIT_AUTOMAKE([ 1.11 foreign silent-rules subdir-objects ])
instead of代替
# Enable quiet compiles on automake 1.11. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
but this is starting to get off-topic.但这开始离题了。
To help others I'll post this as a suggested answer, credit goes to ndim really, this is just putting their answer into a Bitbake format.为了帮助其他人,我会将其作为建议的答案发布,这确实归功于ndim ,这只是将他们的答案放入 Bitbake 格式。 My recipe layout is as follows:
我的食谱布局如下:
└── helloworld
├── files
│ ├── config.h
│ └── helloworld.c
└── helloworld_0.1.bb
helloworld.c is based on the Yocto manual example: helloworld.c 基于 Yocto 手册示例:
#include <stdio.h>
#include "config.h"
int main() {
printf("Hello, World!\n");
printf("PE = %s, PV = %s, PR = $s\n", PE, PV, PR);
printf("YOCTO_BUILD_VERSION = %s\n", YOCTO_BUILD_VERSION);
return 0;
}
config.h:配置.h:
#define PE "1"
#define PV "2"
#define PR "3"
& finally helloworld_0.1.bb: & 最后是 helloworld_0.1.bb:
SUMMARY = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://helloworld.c \
file://config.h \
"
S = "${WORKDIR}"
TARGET_CC_ARCH += "${LDFLAGS}"
do_configure() {
# Make clean required?
echo "#define YOCTO_BUILD_VERSION \"${PR}\"" >> config.h
}
do_compile() {
${CC} helloworld.c -o helloworld
}
do_install() {
install -d ${D}${bindir}
install -m 0755 helloworld ${D}${bindir}
}
This compiles without issue but I need to try it on a board.这编译没有问题,但我需要在板上尝试。
For an autotools build I think the do_compile may need to be replaced with EXTRA_OECONF but I need to try it out.对于自动工具构建,我认为 do_compile 可能需要替换为 EXTRA_OECONF,但我需要尝试一下。
If anyone comes up with a better way I'd be grateful to see it.如果有人提出更好的方法,我将不胜感激。
Thanks for all the help!感谢所有的帮助!
A possible further refinement on this answer is below using sed.下面使用 sed 对此答案进行可能的进一步改进。
#include <stdio.h>
#include "config.h"
int main() {
printf("Hello, World!\n");
printf("Yocto build version = YOCTO_BUILD_VER");
return 0;
}
& in the Yocto recipe: &在 Yocto 食谱中:
PV = "0.9.1"
do_configure_prepend() {
# Amend src/buildVersion.h with Yocto Image Version for display in GUI
( cd ${S}/src;
sed -i 's/YOCTO_BUILD_VER/${PV}/' ${S}/helloworld.c; cd -)
}
I haven't tested this (but something similar does work) but I think the idea is fairly straightforward.我还没有测试过这个(但类似的东西确实有效),但我认为这个想法相当简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.