FYI/FWIW running an external procedure in a Portfile's context
René J.V. Bertin
rjvbertin at gmail.com
Tue Feb 2 10:02:15 PST 2016
H
I've often wanted to run arbitrary code outside of a Portfile (and the port command) but using variables and procedures available when in that Portfile's context. Today I wanted to modify part of a big port's post-destroot without having to go through the whole build process again (slow machine...) so I came up with with a solution which might be of interest to others. The Tcl code below expects to live in a file that is inside the target port's portdir but the principle can of course be used in something much more flexible/generic.
HTH :)
R.
{{{
#!/opt/local/libexec/macports/bin/tclsh8.5
package require Tclx
package require macports
package require Pextlib
package require portutil
# Initialise mport
# This must be done following parse of global options, as some options are
# evaluated by mportinit.
if {[catch {mportinit ui_options global_options global_variations} result]} {
global errorInfo
puts "$errorInfo"
fatal "Failed to initialise MacPorts, $result"
}
# open the port in corresponding to the directory we're living in
if {[catch {set mport [mportopen "file://[file dirname [info script]]"]} result]} {
global errorInfo
ui_debug $errorInfo
ui_error "Unable to open port: $result"
return 1
}
# get the interpreter that was used for evaluating code inside the Portfile
set portinterp [ditem_key ${mport} workername]
# One can export a number of variables of interest from that interpreter like so:
# set qt_cmake_module_dir [$portinterp eval set "qt_cmake_module_dir"]
# but it is much more practical to insert the code to run into the interpreter,
# and run it there.
# http://wiki.tcl.tk/15349
proc inject {name} {
if {[info exists ::auto_index($name)]} {
set body "# $::auto_index($name)\n"
} else {
set body ""
}
append body [info body $name]
set argl {}
foreach a [info args $name] {
if {[info default $name $a def]} {
lappend a $def
}
lappend argl $a
}
list proc $name $argl $body
}
# the code we want to run, written exactly like it would inside the Portfile:
proc fix_cmake_modules {} {
global destroot subport
ui_msg "${subport} has ${destroot}"
# snip
}
# inject the above procedure into $portinterp
$portinterp eval [inject "fix_cmake_modules"]
# evaluate the new procedure
$portinterp eval "fix_cmake_modules"
mportclose ${mport}
mportshutdown
}}}
More information about the macports-dev
mailing list