[Warning: lengthy post, and probably boring to most.] My Bitbake "Hello World" is a little more than a basic "Hello World". It's idea is to incorporate a layer and use a structure similar to what OE and Yocto are using. You can do it simpler if you want to. I did this a while ago with Bitbake 1.12.0. I would think it works with newer versions too although I have not tested it. This is the layout I am using: bbtest/ ├── conf │ ├── bblayers.conf │ └── bitbake.conf ├── downloads │ └── /* need to create but will be populated with downloads */ ├── meta-test │ ├── classes │ │ └── base.bbclass │ ├── conf │ │ └── layer.conf │ └── recipes-test │ └── nano │ └── nano.bb └── tmp └── /* will be created and populated when building */ The first thing Bitbake looks for is a conf/bblayers.conf file in the directory you started it from. This file must provide an initial setting for BBPATH: bblayers.conf: BBPATH := "${TOPDIR}" BBFILES ?= "" BBLAYERS = " \ ${TOPDIR}/meta-test \ " Without BBPATH Bitbake will not find any conf/.conf files and recipe files at all. It will also not find bitbake.conf. I simply copied bitbake.conf from the Bitbake download and edited DL_DIR: bitbake.conf: # comments omitted B = "${S}" CVSDIR = "${DL_DIR}/cvs" DEPENDS = "" DEPLOY_DIR = "${TMPDIR}/deploy" DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images" DL_DIR = "${TOPDIR}/downloads" FETCHCOMMAND = "" FETCHCOMMAND_cvs = "/usr/bin/env cvs -d${CVSROOT} co ${CVSCOOPTS} ${CVSMODULE}" FETCHCOMMAND_svn = "/usr/bin/env svn co ${SVNCOOPTS} ${SVNROOT} ${SVNMODULE}" FETCHCOMMAND_wget = "/usr/bin/env wget -t 5 --passive-ftp -P ${DL_DIR} ${URI}" FILESDIR = "${@bb.utils.which(bb.data.getVar('FILESPATH', d, 1), '.')}" FILESPATH = "${FILE_DIRNAME}/${PF}:${FILE_DIRNAME}/${P}:${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/files:${FILE_DIRNAME}" FILE_DIRNAME = "${@os.path.dirname(bb.data.getVar('FILE', d))}" GITDIR = "${DL_DIR}/git" IMAGE_CMD = "_NO_DEFINED_IMAGE_TYPES_" IMAGE_ROOTFS = "${TMPDIR}/rootfs" MKTEMPCMD = "mktemp -q ${TMPBASE}" MKTEMPDIRCMD = "mktemp -d -q ${TMPBASE}" OVERRIDES = "local:${MACHINE}:${TARGET_OS}:${TARGET_ARCH}" P = "${PN}-${PV}" PERSISTENT_DIR = "${TMPDIR}/cache" PF = "${PN}-${PV}-${PR}" PN = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[0] or 'defaultpkgname'}" PR = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[2] or 'r0'}" PROVIDES = "" PV = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[1] or '1.0'}" RESUMECOMMAND = "" RESUMECOMMAND_wget = "/usr/bin/env wget -c -t 5 --passive-ftp -P ${DL_DIR} ${URI}" S = "${WORKDIR}/${P}" SRC_URI = "file://${FILE}" STAMP = "${TMPDIR}/stamps/${PF}" SVNDIR = "${DL_DIR}/svn" T = "${WORKDIR}/temp" TARGET_ARCH = "${BUILD_ARCH}" TMPDIR = "${TOPDIR}/tmp" UPDATECOMMAND = "" UPDATECOMMAND_cvs = "/usr/bin/env cvs -d${CVSROOT} update ${CVSCOOPTS}" UPDATECOMMAND_svn = "/usr/bin/env svn update ${SVNCOOPTS}" WORKDIR = "${TMPDIR}/work/${PF}" PERSISTENT_DIR = "${TMPDIR}/cache" That's more than you need but it's convenient. Bitbake will require a base.bbclass file somewhere in a classes subdirectory of BBPATH. I used the base.bbclass file from the Bitbake download. As a minimum it should contain a do_build task. That's the target that Bitbake invokes by default if you do not use the -c option explicitly. It's empty and does not do anything but it functions as an anchor for tasks you define in your recipes: base.bbclass: # comments omitted die() { bbfatal "$*" } bbnote() { echo "NOTE:" "$*" } bbwarn() { echo "WARNING:" "$*" } bbfatal() { echo "FATAL:" "$*" exit 1 } addtask showdata do_showdata[nostamp] = "1" python do_showdata() { import sys # emit variables and shell functions bb.data.emit_env(sys.__stdout__, d, True) # emit the metadata which isnt valid shell for e in bb.data.keys(d): if bb.data.getVarFlag(e, 'python', d): sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1))) } addtask listtasks do_listtasks[nostamp] = "1" python do_listtasks() { import sys for e in bb.data.keys(d): if bb.data.getVarFlag(e, 'task', d): sys.__stdout__.write("%s\n" % e) } addtask build do_build[dirs] = "${TOPDIR}" do_build[nostamp] = "1" python base_do_build () { bb.note("The included, default BB base.bbclass does not define a useful default task.") bb.note("Try running the 'listtasks' task against a .bb to see what tasks are defined.") } EXPORT_FUNCTIONS do_clean do_mrproper do_build Again, it's more than you need. It's just convenient to use it. I put this file inside the layer but you can also create a classes directory in ${TOPDIR} (bbtest in this example). Next, create a layer (meta-bbtest in my example, name does not matter, meta-* is convention). It needs a conf/layer.con file: layer.conf: # We have a metadata layer directory, add to BBPATH BBPATH .= ":${LAYERDIR}" # We have a recipe directory, add to BBFILES BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend" BBFILE_COLLECTIONS += "test" BBFILE_PATTERN_test := "^${LAYERDIR}/" BBFILE_PRIORITY_test = "5" The path expression for the recipes is more complex than necessary, it just follows the convention. Finally a recipe to build the Nano editor: DESCRIPTION = "Recipe to build the 'nano' editor" PN = "nano" PV = "2.2.6" SRC_URI = "http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz" python do_fetch() { bb.note("Downloading source tarball from ${SRC_URI} ...") src_uri = (bb.data.getVar('SRC_URI', d, True) or "").split() if len(src_uri) == 0: bb.fatal("Empty URI") try: bb.fetch.init(src_uri, d) bb.fetch.go(d) except FetchError: bb.fatal("Could not fetch source tarball.") bb.note("Download successful.") } addtask fetch before do_build python do_unpack() { bb.note("Unpacking source tarball ...") os.system("tar x -C ${WORKDIR} -f ${DL_DIR}/${P}.tar.gz") bb.note("Unpacked source tarball.") } addtask unpack before do_build after do_fetch python do_configure() { bb.note("Configuring source package ...") os.system("cd ${WORKDIR}/${P} && ./configure") bb.note("Configured source package.") } addtask configure before do_build after do_unpack python do_compile() { bb.note("Compiling package...") os.system("cd ${WORKDIR}/${P} && make") bb.note("Compiled package.") } addtask compile before do_build after do_configure Nano is an autotooled package. This recipe simply at a very basic level does what you would do manually. OECore's autotools.bbclass is much more sophisticated and so are the fetcher class files. :rjs