Yocto's ROOTFS_POSTPROCESS_COMMAND not working? - yocto

I'm trying to use this variable in order to remove a few unwanted init files after my root FS is generated, following the documentation at:
http://www.yoctoproject.org/docs/1.8/ref-manual/ref-manual.html#migration-1.6-variable-changes-variable-entry-behavior
I've added exactly the same snippet to my recipe (.bb) file, without any luck... what's wrong? This is the code I'm putting in my .bb file:
my_postprocess_function() {
echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}
ROOTFS_POSTPROCESS_COMMAND += "my_postprocess_function; "
The logs don't show any kind of error or warning, just my_postprocess_function is not executed.

I believe there is a bug that manifests itself based on which column you put the closing curly bracket in. Initially, I could not believe that this is the behaviour, but after I tested and confirmed it, here are my results:
$ bitbake --version
BitBake Build Tool Core version 1.28.0
I'm modifying core-image-minimal.bb as follows:
FAILING CASE
SUMMARY = "G5 - A small image just capable of allowing a device to boot."
IMAGE_INSTALL = "packagegroup-core-boot ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}"
IMAGE_LINGUAS = " "
LICENSE = "MIT"
IMAGE_ROOTFS_SIZE ?= "8192"
IMAGE_ROOTFS_EXTRA_SPACE_append = "${#bb.utils.contains("DISTRO_FEATURES", "systemd", " + 4096", "" ,d)}"
inherit core-image
my_postprocess_function() {
echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}
ROOTFS_POSTPROCESS_COMMAND += "my_postprocess_function; "
The above fails silently and does not generate hello.txt
Notice how the } is indented by one space (indenting by any amount other than once space will also fail).
However, if you modify it as follows:
SUCCEEDING CASE
SUMMARY = "G5 - A small image just capable of allowing a device to boot."
IMAGE_INSTALL = "packagegroup-core-boot ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}"
IMAGE_LINGUAS = " "
LICENSE = "MIT"
IMAGE_ROOTFS_SIZE ?= "8192"
IMAGE_ROOTFS_EXTRA_SPACE_append = "${#bb.utils.contains("DISTRO_FEATURES", "systemd", " + 4096", "" ,d)}"
inherit core-image
my_postprocess_function() {
echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}
ROOTFS_POSTPROCESS_COMMAND += "my_postprocess_function; "
then, hello.txt is generated.
The way I found this bug is by moving the 'inherit core-image' line to the end of the file as follows:
DIAGNOSIS
SUMMARY = "G5 - A small image just capable of allowing a device to boot."
IMAGE_INSTALL = "packagegroup-core-boot ${ROOTFS_PKGMANAGE_BOOTSTRAP} ${CORE_IMAGE_EXTRA_INSTALL}"
IMAGE_LINGUAS = " "
LICENSE = "MIT"
IMAGE_ROOTFS_SIZE ?= "8192"
IMAGE_ROOTFS_EXTRA_SPACE_append = "${#bb.utils.contains("DISTRO_FEATURES", "systemd", " + 4096", "" ,d)}"
my_postprocess_function() {
echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}
ROOTFS_POSTPROCESS_COMMAND += "my_postprocess_function; "
inherit core-image
In which case, I got the error:
ERROR: ParseError at ......./recipes-core/images/core-image-minimal.bb:13: Shell function my_postprocess_function is never closed
I mentioned this last part in case anyone else is having weird behaviour and you have exhausted all debugging possibilities.

cyberguijarro only says that his code exists in a .bb recipe but didn't say if that recipe was an image recipe or not.
Since he didn't accept any of the given answers, I'll suggest that his issue was that his code was not in an image recipe.

This is working for me:
my_postprocess_function() {
echo "hello" > ${IMAGE_ROOTFS}/hello.txt
}
ROOTFS_POSTPROCESS_COMMAND_append = " \
my_postprocess_function; \
"

Related

Error detected while processing function SwitchFlowOrTsLsps nvim windows 10

Hello I tried to enter a js file and upon entering I got this error:
Error detected while processing function SwitchFlowOrTsLsps:
line 4:
E121: Undefined variable: state
E15: Invalid expression: (tsserver.state == 'disabled')
Try to find the line that tells me in the different files such as maps, plugin or plugin config, the last one is the one I found it in, before I did not suffer from this error because I was only entering py, cpp and java extension files, I have the coc, but do not download anything for this, I also have the kite installed as a plugin for autocompletion
" HTML, JSX
let g:closetag_filenames = '*.html,*.js,*.jsx,*.ts,*.tsx'
" Lightlane
let g:lightline = {
\ 'active': {
\ 'left': [['mode', 'paste'], [], ['relativepath', 'modified']],
\ 'right': [['kitestatus'], ['filetype', 'percent', 'lineinfo'], ['gitbranch']]
\ },
\ 'inactive': {
\ 'left': [['inactive'], ['relativepath']],
\ 'right': [['bufnum']]
\ },
\ 'component': {
\ 'bufnum': '%n',
\ 'inactive': 'inactive'
\ },
\ 'component_function': {
\ 'gitbranch': 'fugitive#head',
\ 'cocstatus': 'coc#status'
\ },
\ 'colorscheme': 'gruvbox',
\ 'subseparator': {
\ 'left': '',
\ 'right': ''
\ }
\}
" nerdtree
let NERDTreeShowHidden=1
let NERDTreeQuitOnOpen=1
let NERDTreeAutoDeleteBuffer=1
let NERDTreeMinimalUI=1
let NERDTreeDirArrows=1
let NERDTreeShowLineNumbers=1
let NERDTreeMapOpenInTab='\t'
let g:javascript_plugin_flow = 1
" Trigger configuration. Do not use <tab> if you use https://github.com/Valloric/YouCompleteMe.
let g:UltiSnipsSnippetDirectories=[$HOME.'/config/.vim/UltiSnips']
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<S-tab>"
" deoplete
let g:deoplete#enable_at_startup = 1
let g:neosnippet#enable_completed_snippet = 1
" kite
let g:kite_supported_lenguages = ['javascript', 'python']
" coc
autocmd FileType python let b:coc_suggest_disable = 1
autocmd FileType javascript let b:coc_suggest_disable = 1
autocmd FileType scss setl iskeyword+=#-#
command! -bang -nargs=? -complete=dir GFiles
\ call fzf#vim#gitfiles(<q-args>, fzf#vim#with_preview(), <bang>0)
command! -bang -nargs=* Ag
\ call fzf#vim#ag(<q-args>, fzf#vim#with_preview(), <bang>0)
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
" if hidden is not set, TextEdit might fail.
set hidden
" Some servers have issues with backup files, see #649
set nobackup
set nowritebackup
" Better display for messages
set cmdheight=2
" You will have bad experience for diagnostic messages when it's default 4000.
set updatetime=300
" don't give |ins-completion-menu| messages.
set shortmess+=c
" always show signcolumns
set signcolumn=yes
" fugitive always vertical diffing
set diffopt+=vertical
" Use <c-space> to trigger completion.
inoremap <silent><expr> <c-space> coc#refresh()
" Remap keys for gotos
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Highlight symbol under cursor on CursorHold
autocmd CursorHold * silent call CocActionAsync('highlight')
autocmd BufEnter *.js :silent let myIndex = SearchPatternInFile("#flow") | call SwitchFlowOrTsLsps(myIndex)
autocmd BufEnter *.jsx :silent let myIndex = SearchPatternInFile("#flow") | call SwitchFlowOrTsLsps(myIndex)
function! SwitchFlowOrTsLsps(flowIndex)
silent let stats = CocAction("extensionStats")
silent let tsserver = get(filter(copy(stats), function('FindTsServer')), 0)
if(a:flowIndex == 0)
if(tsserver.state == 'disabled')
call CocActionAsync("toggleExtension", "coc-tsserver")
endif
else
if(tsserver.state == 'activated')
call CocActionAsync("toggleExtension", "coc-tsserver")
endif
endif
endfunction
function! FindTsServer(idx, value)
return a:value.id == 'coc-tsserver'
endfunction
let $FZF_DEFAULT_OPTS='--layout=reverse'
let g:fzf_layout = { 'window': 'call FloatingFZF()' }
function! FloatingFZF()
let buf = nvim_create_buf(v:false, v:true)
call setbufvar(buf, '&signcolumn', 'no')
let height = float2nr((&lines - 3) / 2)
let width = float2nr(&columns - (&columns * 2 / 10))
let col = float2nr((&columns - width) / 2)
let row = float2nr((&lines - height) / 2)
let opts = {
\ 'relative': 'editor',
\ 'row': row,
\ 'col': col,
\ 'width': width,
\ 'height': height
\ }
call nvim_open_win(buf, v:true, opts)
endfunction
function! SearchPatternInFile(pattern)
" Save cursor position.
let save_cursor = getcurpos()
" Set cursor position to beginning of file.
call cursor(0, 0)
" Search for the string 'hello' with a flag c. The c flag means that a
" match at the cursor position will be accepted.
let search_result = search(a:pattern, "c")
" Set the cursor back at the saved position. The setpos function was
" used here because the return value of getcurpos can be used directly
" with it, unlike the cursor function.
call setpos('.', save_cursor)
" If the search function didn't find the pattern, it will have
" returned 0, thus it wasn't found. Any other number means that an instance
" has been found.
return search_result
endfunction
How could I solve it?, thanks to all.
Can you try running this command on vim and see if it works?
:CocInstall coc-json coc-tsserver

P4Python does not check out the file in Perforce

I have following piece of code. I'm trying to check out two files from Perforce and put them in a changelist. But run_add does not check the files out. The only thing I see in Perforce is a empty changelist with no files in it.
""" Checks out files from workspace using P4"""
files = ['analyse-location.cfg', 'CMakeLists.txt']
p4 = P4()
# Connect and disconnect
if (p4.connected()):
p4.disconnect()
p4.port = portp4
p4.user = usernameP4
p4.password = passwordP4
p4.client = clientP4
try:
p4.connect()
if p4.connected():
change = p4.fetch_change()
change['Description'] = "Auto"
change['Files'] = []
changeList = p4.save_change(change)[0].split()[1]
for items in files:
abs_path = script_dir + "\\" + items
p4.run_add("-c", changeList, items)
print("Adding file "+ abs_path + " to "+ changeList)
# Done! Disconnect!
p4.disconnect()
except P4Exception:
print("Something went wrong in P4 connection. The errors are: ")
for e in p4.errors:
print(e)
p4.disconnect()
However, when I have instead p4.run("edit", items) it puts the files in the default changelist.It really gets on my nervs. I don't know I am doing that is wrong. The changes list created as well. I use python 3.7 32 bits on Windows
Your script discards the output of the run_add call. Try changing this:
for items in files:
abs_path = script_dir + "\\" + items
p4.run_add("-c", changeList, items)
print("Adding file "+ abs_path + " to "+ changeList)
to:
for items in files:
abs_path = script_dir + "\\" + items
output = p4.run_add("-c", changeList, items)
print("Adding file "+ abs_path + " to "+ changeList)
if output:
print(output)
if p4.errors:
print(p4.errors)
if p4.warnings:
print(p4.warnings)
That will show you the results of the p4 add commands that you're running. Based on the fact that a p4 edit opens the files, I expect you'll find a message like this:
C:\Perforce\test>p4 add foo
//stream/main/foo - can't add existing file
The p4 add and p4 edit commands are not synonymous; one is for adding a new file, one is for editing an existing file. If your script is editing existing files, it should be calling run_edit, not run_add.
I changed my question to following and it worked.
p4.port = portp4
p4.user = usernameP4
p4.password = passwordP4
p4.client = clientP4
try:
p4.connect()
if p4.connected():
change = p4.fetch_change()
change['Description'] = "Auto"
change['Files'] = []
changeList = p4.save_change(change)[0].split()[1]
for items in files:
abs_path = script_dir + "\\" + items
output = p4.run_edit("-c", changeList, items)
print("Adding file "+ abs_path + " to "+ changeList)
if output:
print(output)
if p4.errors:
print(p4.errors)
if p4.warnings:
print(p4.warnings)
p4.disconnect()
except P4Exception:
print("Something went wrong in P4 connection. The errors are: ")
for e in p4.errors:
print(e)
p4.disconnect()
Thanks to #Sam Stafford for his hint. Now it works just like a charm. The key was to change p4.run_add("-c", changelist, items) to p4.run_edit("-c", changelist, items)

How to integrated mender within lk-bootloader base-on Yocto Project

I am new for yocto ,now I use a MTK-demo-board to build a linux-distro base on Yocto. I want to realize OTA by mender followed this tutorial:https://docs.mender.io/1.0/Devices/Integrating-with-U-Boot.
but Mender support u-boot as bootloader by default, the MTK use lk bootloader,Then how to realize this function?
The AP which I used is MT8183,The steps I have done list below:
1. /meta/meta-mediatek/recipes-bsp/lk/lk_2.0.0.0.bb . add follow code:
require recipes-bsp/u-boot/u-boot-mender.inc
PROVIDES += "u-boot"
RPROVIDES_{PN} += "u-boot"
2.cp lk_2.0.0.0 lk-fw-utils_2.0.0.0,and changed the file as behind:
a. delete do_genkey{} function;
b. add EXTRA_OEMAKE_class-target = 'CROSS_COMPILE=${TARGET_PREFIX} CC="${CC} ${CFLAGS} ${LDFLAGS}" V=1'
c. add "oe_runmake env" in function do_compile()
d. add PROVIDES_${PN} = "lk-fw-utils"
RPROVIDES_${PN} = "lk-fw-utils"
DEPENDS += "mtd-utils"
3./build/local.conf,add these code
MENDER_ARTIFACT_NAME = "release-1"
INHERIT += "mender-full"
MACHINE = "aiv8183m1v2"
PREFERRED_VERSION_pn-mender = "1.0.%"
PREFERRED_VERSION_pn-mender-artifact = "1.0.%"
PREFERRED_VERSION_pn-mender-artifact-native = "1.0.%"
DISTRO_FEATURES_append = "systemd"
VIRTUAL-RUNTIME_init_manager = "systemed"
DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
VIRTUAL-RUNTIME_initscripts = ""
IMAGE_FSTYPES = "ext4"
4.execute bitbake-layers add-layer /meta/meta-mender/meta-mender-core
5.bitbake-layers create-layer meta-mylayer,in this layer,I mkdir -p /recipes-mender/mender/files, in directory mender,I touch mender_%.bbappend file as bellow:
FILESEXTARPATHS_prepend := "${THISDIR}/file:"
SRC_URI_append = "file://server.crt"
and put servert.crt in the the file directory.
6.in the mancine.conf(aiv8183m1v2.conf),I have added
PREFERRED_PROVIDER_u-boot-fw-utils = "lk-fw-utils"
PREFERRED_PROVIDER_u-boot = "lk"
IMAGE_INSTALL_append = "kernel-modules"
MENDER_STORAGE_DEVICE = "/dev/mmcblk0"
7./meta-mender/meta-mender-core/classes/mender-full.bbclass
MENDER_FEATURES_ENABLE_append_arm = ""
MENDER_FEATURES_ENABLE_append_aarch64 = ""
the result I expected is the linux can OTA over mender.
But,actual results is the project can't cross build.the log says:
DEBUG: Executing shell function soft_link_to_rootfs
| ln: target ‘mender.bmap’ is not a directory
| WARNING: /home/yewkui/yocto-linux/build/tmp/work/aiv8183m1v2-poky-linux/mtk-image-openmm-aiv/1.0-r0/temp/run.soft_link_to_rootfs.1347217:1 exit 1 from 'ln -nfs mtk-image-openmm-aiv-aiv8183m1v2-20181224064735.rootfs.ext4 mender mender.bmap /home/yewkui/yocto-linux/build/tmp/deploy/images/aiv8183m1v2/rootfs.ext4 mender mender.bmap'
| DEBUG: Python function do_rootfs finished
| ERROR: Function failed: soft_link_to_rootfs (log file is located at /home/yewkui/yocto-linux/build/tmp/work/aiv8183m1v2-poky-linux/mtk-image-openmm-aiv/1.0-r0/temp/log.do_rootfs.1347217)
ERROR: Task (/home/yewkui/yocto-linux/meta/poky/../meta-mediatek-mt8183/recipes-aiv/images/mtk-image-openmm-aiv.bb:do_rootfs) failed with exit code '1'
NOTE: Tasks Summary: Attempted 2392 tasks of which 2391 didn't need to be rerun and 1 failed.
NOTE: Writing buildhistory
Maybe I am wrong at first step,but how to realize the OTA by yocto base on MTK lk-bootloader,please help! thanks a lot!

fetching from local directory

Posted a question on Yocto mailing list but didn't get an answer. Hopefully someone can provide one here.
We are storing some of the source code locally on a machine. Found
this on how to do it, https://stackoverflow.com/a/27834916/1636521,
but for some reason it doesn't work for me. I'm pretty sure I'm
missing something but don't know what exactly.
Here is my recipe
SUMMARY = ""
DESCRIPTION = ""
# Licensing Meta-data
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "${AUTOREV}"
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
SRC_URI += " \
file://app.tgz \
"
DEPENDS += "\
libevent \
"
do_compile () {
export SWROOT=${S}/../app
oe_runmake
}
do_install () {
:
}
And here is the error that I'm getting:
Loading cache: 100%
|###########################################################################################################|
Time: 0:00:01
Loaded 3265 entries from dependency cache.
WARNING: /home/user/projects/petalinux-build-system/sources/core/../meta-piccard/recipes-piccard/cpe/cpe.bb:
Unable to get checksum for cpe SRC_URI entry app.tgz: file could not
be found
Parsing recipes: 100%
|#########################################################################################################|
Time: 0:00:04
Parsing of 2476 .bb files complete (2470 cached, 6 parsed). 3269
targets, 229 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Build Configuration:
BB_VERSION = "1.32.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "universal"
TARGET_SYS = "arm-xilinx-linux-gnueabi"
MACHINE = "zynq-generic"
DISTRO = "petalinux"
DISTRO_VERSION = "2017.3"
TUNE_FEATURES = "arm armv7a vfp thumb neon
callconvention-hard cortexa9"
TARGET_FPU = "hard"
meta
meta-poky = "HEAD:8506cec55de8950e89a4d3e786860f1086782587"
meta-perl
meta-systemd
meta-gpe
meta-python
meta-efl
meta-ruby
meta-filesystems
meta-gnome
meta-multimedia
meta-networking
meta-webserver
meta-xfce
meta-initramfs
meta-oe = "HEAD:a9887ac249b81fcac3007244d0c807c71b73acef"
meta-linaro-toolchain = "HEAD:39860f6c7af0858981cc004bbe4f4c421f6be607"
meta-qt5 = "HEAD:eec778bfb9a0b5494d593a2d7bb02c027b641835"
meta-xilinx = "HEAD:04a45809e0bc42b35c88f8a08305d82fd25e97cf"
meta-xilinx-tools = "HEAD:37eff634934efac72d3e2eabb7c4f8d0c8a36fbb"
meta-petalinux = "HEAD:d74ceaef26e606c2761edfc3446d0ad3c3cc8b8e"
meta-virtualization = "HEAD:cbfd4376d5e9d229f857151ffdfb57fbc6c0c40d"
meta-openamp = "HEAD:cfeca8988418e4967f0d6df828d23a1540ae25a0"
meta-swupdate = "HEAD:6c066d36b1c3c6d46f16c09efe5fb7681bbf3dc5"
meta-piccard = "master:9f114a33df76a3c3f40eca12b7195ff8ebaad876"
workspace = "HEAD:51fa75c5477e29285bbbe810f4327b26d80d511d"
Here is the ls of the recipes directory,
$ ls ~/projects/petalinux-build-system/sources/meta-piccard/recipes-piccard/cpe/files
app app.tgz
The output of
bitbake cpe -e | grep FILESEXTRAPATHS
produces the following line
FILESEXTRAPATHS="/home/userl/projects/petalinux-build-system/sources/core/../meta-piccard/recipes-piccard/cpe/files:__default:"
What am I missing?
You need to add the license file checksum, do like below commands
md5sum apps.tgz
e.g :
siva#siva-Vostro-3268:~$ md5sum hello.tar.gz
62390830e7933767d5e3bd080d619c70 hello.tar.gz
Then copy the number and paste into you recipe(.bb)using the variable see below,
SRC_URI[md5sum] = "62390830e7933767d5e3bd080d619c70"
or
SRC_URI += "file://app.tgz;md5=xxxxxx"

Examples of using SCons with knitr

Are there minimal, or even larger, working examples of using SCons and knitr to generate reports from .Rmd files?
kniting an cleaning_session.Rmd file from the command line (bash shell) to derive an .html file, may be done via:
Rscript -e "library(knitr); knit('cleaning_session.Rmd')".
In this example, Rscript and instructions are fed to a Makefile:
RMDFILE=test
html :
Rscript -e "require(knitr); require(markdown); knit('$(RMDFILE).rmd', '$(RMDFILE).md'); markdownToHTML('$(RMDFILE).md', '$(RMDFILE).html', options=c('use_xhtml', 'base64_images')); browseURL(paste('file://', file.path(getwd(),'$(RMDFILE).html'), sep=''
In this answer https://stackoverflow.com/a/10945832/1172302, there is reportedly a solution using SCons. Yet, I did not test enough to make it work for me. Essentially, it would be awesome to have something like the example presented at https://tex.stackexchange.com/a/26573/8272.
[Updated] One working example is an Sconstruct file:
import os
environment = Environment(ENV=os.environ)
# define a `knitr` builder
builder = Builder(action = '/usr/local/bin/knit $SOURCE -o $TARGET',
src_suffix='Rmd')
# add builders as "Knit", "RMD"
environment.Append( BUILDERS = {'Knit' : builder} )
# define an `rmarkdown::render()` builder
builder = Builder(action = '/usr/bin/Rscript -e "rmarkdown::render(input=\'$SOURCE\', output_file=\'$TARGET\')"',
src_suffix='Rmd')
environment.Append( BUILDERS = {'RMD' : builder} )
# define source (and target files -- currently useless, since not defined above!)
# main cleaning session code
environment.RMD(source='cleaning_session.Rmd', target='cleaning_session.html')
# documentation of the Cleaning Process
environment.Knit(source='Cleaning_Process.Rmd', target='Cleaning_Process.html')
# documentation of data
environment.Knit(source='Code_Book.Rmd', target='Code_Book.html')
The first builder calls the custom script called knit. Which, in turn, takes care of the target file/extension, here being cleaning_session.html. Likely the suffix parameter is not needed altogether, in this very example.
The second builder added is Rscript -e "rmarkdown::render(\'$SOURCE\')"'.
The existence of $TARGETs (as in the example at Command wrapper) ensures SCons won't repeat work if a target file already exists.
The custom script (whose source I can't retrieve currently) is:
#!/usr/bin/env Rscript
local({
p = commandArgs(TRUE)
if (length(p) == 0L || any(c('-h', '--help') %in% p)) {
message('usage: knit input [input2 input3] [-n] [-o output output2 output3]
-h, --help to print help messages
-n, --no-convert do not convert tex to pdf, markdown to html, etc
-o output filename(s) for knit()')
q('no')
}
library(knitr)
o = match('-o', p)
if (is.na(o)) output = NA else {
output = tail(p, length(p) - o)
p = head(p, o - 1L)
}
nc = c('-n', '--no-convert')
knit_fun = if (any(nc %in% p)) {
p = setdiff(p, nc)
knit
} else {
if (length(p) == 0L) stop('no input file provided')
if (grepl('\\.(R|S)(nw|tex)$', p[1])) {
function(x, ...) knit2pdf(x, ..., clean = TRUE)
} else {
if (grepl('\\.R(md|markdown)$', p[1])) knit2html else knit
}
}
mapply(knit_fun, p, output = output, MoreArgs = list(envir = globalenv()))
})
The only thing, now, necessary is to run scons.