How do you guys pass valued parameter to scons ? I went through its documentation and unfortunately it's still unclear to me. I've never used it before.
Please consider this build script.
Here is code snippet from it
add_option( "boost-version", "boost version for linking(1_38)" , 1 , True , "boostVersion" )
boostVersion = GetOption( "boostVersion" )
if boostVersion is None:
boostVersion = ""
else:
boostVersion = "-" + boostVersion
I tried calling scons --boost-version=1.51 and tried scons --boostVersion=1.51 and none of it worked.
You could use arguments:
You call scons boost-version=1.51 on the commandline
Then, to fetch the value in the SConscript:
boostVersion = defaultBoostVersion
if 'boost-version' in ARGUMENTS:
boostVersion = ARGUMENTS["boost-version"]
or, as elmo suggested:
boostVersion = ARGUMENTS.get("boost-version", defaultBoostVersion)
The scons documentation have more information the same page also describe how to use
AddOption command that you have tried earlier. It can be used also, but arguments are (to me at least) easier to understand.
Related
When in Powershell I can run the following command
.\exiftool.exe '-GPSLatitude*=56.9359839838' '-GPSLongitude*=-4.4651045874' DSC01008.JPG '-overwrite_original_in_place'
This works just fine, and the placement of single quotes around those params are required. I went through various iterations of different placements and the above is the only way I could get it to work.
My issue is -> That I'm trying to replace those values with programmatic values. As in something like the following.
$lat = 56.9359839838
$lon = -4.4651045874
$fileName = 'DSC01008.JPG'
.\exiftool.exe -GPSLatitude*=$lat -GPSLongitude*=$lon $fileName '-overwrite_original_in_place'
I've gone through numerous attempts with single/backtick/double quotes, trying to concatenate and anything else I can think of - but that magic format hasn't appeared!
Any thoughts on what I am doing wrong?
As an example I thought this was really work, yet didn't. But it matches up with the command that does when it's hard coded.
EDIT/Update -
The * are required inside the command, otherwise it doesn't work. They are used to get around not passing in reference locators.
If you were to run these commands in PS, then these are the errors that you get.
cmd ->
.\exiftool.exe "-GPSLatitude*=$lat" "-GPSLongtitude*=$lon" $FileName
error ->
No Error, but the file does not get any GPS tags. Nothing actually modified.
cmd ->
$combLat = "`'-GPSLatitude*=$lat`'" # + "
$combLon = "`'-GPSLongitude*=$lon`'" # + "'"
$combined = "$combLat $combLon $fileName"
# $combined will output the following: '-GPSLatitude*=-3.4651045874' '-GPSLongitude*=55.9359839838' 'E:\CameraAddGPS\TestFolder\DSC01010.JPG'
.\exiftool.exe $combined
error ->
.\exiftool.exe : Wildcards don't work in the directory specification
At E:\CameraAddGPS\TestFolder\demo.ps1:25 char:1
+ .\exiftool.exe $combined
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Wildcards don't...y specification:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
No matching files
Update 2 -
This will work, but I do not want to update the image twice.
$combLat = '-GPSLatitude*=' + $lat
$combLon = '-GPSLongitude*=' + $lon
.\exiftool.exe $combLat $fileName '-overwrite_original_in_place'
.\exiftool.exe $combLon $fileName '-overwrite_original_in_place'
The problem is that the latitude and longtitude argumets are "attached" directly to the -GPSLatitute* and -GPSLongtitude* parameter names after the = sign. (The - initial character prevents PowerShell from invoking variable expansion - see GitHub issue #14587.)
One way to work around this is to wrap the -GPSLatitude* and -GPSLongtitude* parameters in " quotes; e.g.
.\exiftool.exe "-GPSLatitude*=$lat" "-GPSLongtitude*=$lon" $FileName -overwrite_original_in_place
Another way is to prefix the - character with a backquote (`); e.g.:
.\exiftool.exe `-GPSLatitude*=$lat `-GPSLongitude*=$lon $fileName -overwrite_original_in_place
I prefer the first variation as it seems more readable to me.
Aside #1: There's no need for the single ' quotes around that last parameter. They don't hurt, but they don't do anything, either.
Aside #2: You can see the actual command line that PowerShell is running if you prefix your command with the getargs command available here:
https://github.com/Bill-Stewart/getargs/releases
The getargs utility outputs the actual command line without any parsing or interpretation and will show the actual command that PowerShell will run.
Is it possible to add multiple commands using karate.fork()? I tried adding the commands using ; or && separation but the second command doesn't seem to be getting executed.
I am trying to cd to a particular directory before executing bash on a shell script.
* def command =
"""
function(line) {
var proc = karate.fork({ redirectErrorStream: false, useShell: true, line: line });
proc.waitSync();
karate.set('sysOut', proc.sysOut);
karate.set('sysErr', proc.sysErr);
karate.set('exitCode', proc.exitCode);
}
"""
* call command('cd ../testDirectory ; bash example.sh')
Note that instead of line - args as an array of command line arguments is supported, so try that as well - e.g. something like:
karate.fork({ args: ['cd', 'foo;', 'bash', 'example.sh'] })
But yes this may need some investigation. You can always try to have all the commands in a single batch file which should work.
Would be good if you can try the 1.0 RC since some improvements may have been added: https://github.com/intuit/karate/wiki/1.0-upgrade-guide
I'm trying to write a Builder in SCons to call a command line executable with some arguments that are generated by a (series of) python functions.
cmdVars = Variables(None, ARGUMENTS)
cmdVars.AddVariables(
EnumVariable('DEBUG', 'help for debug', 'a', allowed_values=('a','b','c')),
PathVariable('CLI', 'path to cli exe', 'C:\...\blah.exe', PathVariable.PathIsFile)
)
env = Environment(variables = cmdVars)
def generateSomeExtraBitsDependingOnFlag(debug):
if (debug == 'a'):
return "-DDEBUG -DBlah myTextHere"
return ''
myBuilder = Builder(
action = '"$CLI" generateSomeExtraBitsDependingOnFlag("$DEBUG")'
)
<extra stuff to add myBuilder to env and call env.myBuilder>
The "$CLI" input is correctly substituted to output (when calling scons) something like C:\Program Files\...\blah.exe but the output from the function never appears, regardless of the DEBUG setting.
Prepending print(debug) inside the function prints $DEBUG whilst parsing the SConstruct file (so it's not surprising it doesn't match the if condition).
Do I just need to use a Generator or follow the instructions in chapter 18.4 (Builders That Execute Python Functions) to make this work? Is the section Writing Builders That Execute External Commands not what I want here?
I suspect that given understanding, the user guide is clear, but without already knowing the answer, the guide is a little opaque to me.
Try this:
cmdVars = Variables(None, ARGUMENTS)
cmdVars.AddVariables(
EnumVariable('DEBUG', 'help for debug', 'a', allowed_values=('a','b','c')),
PathVariable('CLI', 'path to cli exe', 'C:\...\blah.exe', PathVariable.PathIsFile)
)
env = Environment(variables = cmdVars)
def generateSomeExtraBitsDependingOnFlag(source, target, env, for_signature):
if (env['DEBUG'] == 'a'):
return "-DDEBUG -DBlah myTextHere"
return ''
env['generateSomeExtraBitsDependingOnFlag'] =generateSomeExtraBitsDependingOnFlag
myBuilder = env.Builder(
action = '"$CLI" ${generateSomeExtraBitsDependingOnFlag}'
)
env.Append(BUILDERS = {'myBuilder' : myBuilder})
env.myBuilder('dummy','input')
I want build files based on variables that are assigned in the SConstruct file. As in this example:
import os
env = Environment(ENV = os.environ)
def text_file_maker(target, source, env):
with open(str(target[0]), "w") as text_file:
text_file.write(env['my_text'])
return 0
env.Append( BUILDERS = {'Make_text' : Builder(action = text_file_maker)})
env.Make_text(target = 'sour.txt',
source = None,
my_text = 'lemon')
env.Make_text(target = 'sweet.txt',
source = None,
my_text = 'apple')
Running this script generates two text files with the content 'lemon' and 'apple'. If I'm running the script again, SCons correctly detects that the targets exist:
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
Now if I'm changing one target, e.g:
env.Make_text(target = 'sweet.txt',
source = None,
my_text = 'orange')
and run the script, I'll get scons: '.' is up to date. and the content 'orange' is not written to sweet.txt.
I could specify a dependency:
Depends(['sweet.txt', 'sour.txt'], 'SConstruct')
but that forces a rebuild for any change in my SConstruct script.
How can I make SCons recognise changes in the SConstruct script that affects the targets?
This could be a very simple question, sorry if I missed something obvious.
You're example very closely resembles the answer which is in the manpage (Search for "Action Objects"):
https://scons.org/doc/production/HTML/scons-man.html
The third and succeeding arguments, if present, may either be a construction variable or a list of construction variables whose values will be included in the signature of the Action when deciding whether a target should be rebuilt because the action changed. The variables may also be specified by a varlist= keyword parameter; if both are present, they are combined. This is necessary whenever you want a target to be rebuilt when a specific construction variable changes. This is not often needed for a string action, as the expanded variables will normally be part of the command line, but may be needed if a Python function action uses the value of a construction variable when generating the command line.
def build_it(target, source, env):
# build the target from the 'XXX' construction variable
open(target[0], 'w').write(env['XXX'])
return 0
# Use positional arguments.
a = Action(build_it, '$STRINGIT', ['XXX'])
# Alternatively, use a keyword argument.
a = Action(build_it, varlist=['XXX'])
So in your case change:
env.Append( BUILDERS = {'Make_text' : Builder(action = text_file_maker)})
To
tfb_action = Action(text_file_maker, varlist=['my_text'])
env.Append( BUILDERS = {'Make_text' : Builder(action = tfb_action)})
At the moment I'm using some magic to get the current git revision into my scons builds.. I just grab the version a stick it into CPPDEFINES.
It works quite nicely ... until the version changes and scons wants to rebuild everything, rather than just the files that have changed - becasue the define that all files use has changed.
Ideally I'd generate a file using a custom builder called git_version.cpp and
just have a function in there that returns the right tag. That way only that one file would be rebuilt.
Now I'm sure I've seen a tutorial showing exactly how to do this .. but I can't seem to track it down. And I find the custom builder stuff a little odd in scons...
So any pointers would be appreciated...
Anyway just for reference this is what I'm currently doing:
# Lets get the version from git
# first get the base version
git_sha = subprocess.Popen(["git","rev-parse","--short=10","HEAD"], stdout=subprocess.PIPE ).communicate()[0].strip()
p1 = subprocess.Popen(["git", "status"], stdout=subprocess.PIPE )
p2 = subprocess.Popen(["grep", "Changed but not updated\\|Changes to be committed"], stdin=p1.stdout,stdout=subprocess.PIPE)
result = p2.communicate()[0].strip()
if result!="":
git_sha += "[MOD]"
print "Building version %s"%git_sha
env = Environment()
env.Append( CPPDEFINES={'GITSHAMOD':'"\\"%s\\""'%git_sha} )
You don't need a custom Builder since this is just one file. You can use a function (attached to the target version file as an Action) to generate your version file. In the example code below, I've already computed the version and put it into an environment variable. You could do the same, or you could put your code that makes git calls in the version_action function.
version_build_template="""/*
* This file is automatically generated by the build process
* DO NOT EDIT!
*/
const char VERSION_STRING[] = "%s";
const char* getVersionString() { return VERSION_STRING; }
"""
def version_action(target, source, env):
"""
Generate the version file with the current version in it
"""
contents = version_build_template % (env['VERSION'].toString())
fd = open(target[0].path, 'w')
fd.write(contents)
fd.close()
return 0
build_version = env.Command('version.build.cpp', [], Action(version_action))
env.AlwaysBuild(build_version)