qmake: how to supply multiple variables via command-line? - qmake

qmake allows to supply a variables via a command-line interface like this:
qmake "CONFIG += release" "MY_VAR = hello"
So i can use $$MY_VAR inside a .pro file. But is it possible to suply more than one variable such way? I have tried
qmake "CONFIG += release" "MY_VAR = hello" "MY_ANOTHER_VAR = hi"
But it did not work (raises error). Any hints?

The question is misleading. You CAN supply any number of variables.
.pro file:
....
message($$VAR1)
message($$VAR2)
qmake run:
qmake ... "VAR1=VALUE1" "VAR2=VALUE2"
compiler output:
09:40:13: Running build steps for project test...
09:40:13: Starting: "c:\qtsdk\desktop\qt\4.8.1\mingw\bin\qmake.exe" D:\tmp\test\test.pro -r -spec win32-g++ "CONFIG+=declarative_debug" "VAR1=VALUE1" "VAR2=VALUE2"
Project MESSAGE: VALUE1
Project MESSAGE: VALUE2
Project MESSAGE: VALUE1
Project MESSAGE: VALUE2
Project MESSAGE: VALUE1
Project MESSAGE: VALUE2
09:40:14: The process "c:\qtsdk\desktop\qt\4.8.1\mingw\bin\qmake.exe" exited normally.

qmake can access environment variables via $$() syntax (internal variables are accessed with $${} syntax). This can be used to pass any number of variables to qmake.

Related

How to fail a Bazel build on a rule failure?

I am using Bazel rules in NodeJS in my application. The aim is to simply lint a set of files and fail the build if linting fails. What I'm currently experiencing is that the build is successful despite lint errors.
Here's a part of my BUILD file:
load("#npm//htmlhint:index.bzl", "htmlhint")
filegroup(
name = "htmldata",
srcs = glob(["**/*.html"]),
)
htmlhint(
name = "compile",
data = [
"htmlhint.conf",
"//:htmldata"
],
args = [
"--config",
"htmlhint.conf",
"$(locations //:htmldata)"
]
)
I first load the hinting library, then I define a filegroup for all the HTML files that I want to lint. Afterward, I use the rule with its data and arguments.
To run the build, I use the default option via npm script: bazel build //...
Your build file is working as expected. Unfortunately it doesn't do what you want, because when you load the macro from #npm//htmlhint:index.bzl it sets up the nodejs binary which is a runnable target, which means that it will only create runfiles + executable when building. In this case, the build will not run the library.
There are several options to do what you want:
Use the htmlhint_test macro to create a test target.
Create a custom rule that will use the nodejs binary to build some artefacts. In this case, you can force the build to fail.
However, I suggest using the first approach, because if htmlhint is a linting tool, it won't produce any meaningful outputs and is best to keep it as part of the test suite.
Here's what you need to do to set up the compile target as a test target
diff --git a/BUILD.bazel b/BUILD.bazel
index 4e58ac5..3db5dbb 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
## -1,11 +1,11 ##
-load("#npm//htmlhint:index.bzl", "htmlhint")
+load("#npm//htmlhint:index.bzl", "htmlhint_test")
filegroup(
name = "htmldata",
srcs = glob(["**/*.html"]),
)
-htmlhint(
+htmlhint_test(
name = "compile",
data = [
"htmlhint.conf",
Then you can check it with bazel test //....
If you want to see the output just run your compile target with bazel run //path/to:compile

how to build cc_test for android using bazel

I am trying to use bazel as build system.
My project looks like this:
a static library which contains a bunch of classes and functions
a dynamic library (so/dll) using the same code as the static library (need to have it because of windows, cc_library rule does not automatically build a dll on windows)
a cc_test rule which build an executable. it contains unit tests based on google test framework
It works when running on Windows and Linux.
The test rule fails when trying to build Android like this
bazel build //unit:unit --crosstool_top=#androidndk//:default_crosstool --cpu=armeabi-v7a
INFO: Invocation ID: b7c88128-3448-4eb7-bf25-ce8269895956 ERROR: ../yg32wcuz/external/androidndk/BUILD.bazel:39:1: in cc_toolchain_suite rule #androidndk//:toolchain-gnu-libstdcpp: cc_toolchain_suite '#androidndk//:toolchain-gnu-libstdcpp' does not contain a toolchain for cpu 'x64_windows'
ERROR: Analysis of target '//unit:unit' failed; build aborted: Analysis of target '#androidndk//:toolchain-gnu-libstdcpp' failed; build aborted
It looks like that bazel seems to have problem with cc_test and android toolchain
Is there any way to build and run an executable for android using bazel? Maybe I missed some command line arguments
Edit:
tried the solution below and added a sh_test rule but it fails again
using #androidsdk//:adb and leads to the following error
ERROR: missing input file '#androidsdk//:platform-tools/adb'
ERROR: unit/BUILD:61:1: //unit:unit_android: missing input file '#androidsdk//:platform-tools/adb' Target //unit:unit_android failed to build
ERROR: unit/BUILD:61:1 1 input file(s) do not exist
I also need to use $ANDROID_HOME/platform-tools/adb to get the adb binary. external/androidsdk/platform-tools/adb does not work. my BUILD file is in a sub folder of the workspace, maybe this is the issue.
removing #androidsdk//:adb fixes this error. there are some adjustments needed in sh_test rule like:
sh_test(
name = "unit_android",
srcs = ["unit_android.sh"],
data = [
":unit",
#"#androidsdk//:adb",
],
deps = [
"#bazel_tools//tools/bash/runfiles", # to access the manifest
],
)
using runfiles dependency allows me to access the binary via $(rlocation ..) in shell script. but now there seems to be another issue:
when using 'bazel run':
It looks like that bazel is trying to upload the file to msys shell (i am using windows) and not to the device:
adb: error: failed to copy '.../_bazel_exb_a/yg32wcuz/execroot/test/bazel-out/armeabi-v7a-fastbuild/bin/unit/unit' to 'C:/Development/msys2/data/local/tmp/unit'
when using 'bazel test':
it just states an error and the content of test log is
unknown parameter - /users
Edit 2:
WORKSPACE file about android sdk/ndk
android_ndk_repository(
name = "androidndk", # Required. Name *must* be "androidndk".
api_level = 26
)
android_sdk_repository(
name = "androidsdk", # Required. Name *must* be "androidsdk".
api_level = 26
)
In both case I assume env var ANDROID_NDK_HOME (points to ndk), ANDROID_SDK_HOME (points to sdk) and ANDROID_HOME (points to sdk) are set. I also checked the external dir, sdk is in there. Removing "#androidsdk//:adb" seem to work but the bazel shell environment now tries to add a prefix before "/data/local/tmp" and tries to upload to a non existing folder.
forget about the issue with "/users" (windows path issue ...)
--crosstool_top by itself sets both the target and host crosstool, so you may just need to set --host_crosstool_top back to the default: --host_crosstool_top=#bazel_tools//tools/cpp:toolchain
Edit:
Running the test on a device is unfortunately not supported out of the box by bazel test. There needs to be some test runner that knows how to put the test on the device, run it, and collect the results. A very simple version of that might look like:
test.cc:
int main(int argc, char** argv) {
// Test always passes.
// Return non-zero for test failure.
return 0;
}
example_android_cc_test.sh:
adb=external/androidsdk/platform-tools/adb
# The test requires a running emulator or connected device.
# The name of the cc_test binary can be passed in using the
# args attribute of sh_test to make this script generic.
$adb push example_test /data/local/tmp
# adb shell returns the exit code of the command
# that was executed, and the exit code of the
# test shell script determines if the sh_test target
# passes or fails.
$adb shell "/data/local/tmp/example_test"
BUILD:
cc_test(
name = "example_test",
srcs = ["test.cc"],
linkopts = ["-pie"],
linkstatic = 1,
)
sh_test(
name = "example_android_cc_test",
srcs = ["example_android_cc_test.sh"],
data = [
":example_test",
"#androidsdk//:adb",
],
)
Note that this approach is not hermetic because it relies on an emulator to already be running, or a device to be already connected. It's possible to start an emulator as part of the test, but that's more involved.

Scons Environment() strange behavior

I am playing around with scons build . When i use the following to import my system path :
env = Environment(ENV={'PATH' : os.environ['PATH']})
assuming i am using gcc compiler , the path is set in C:\cygwin\bin
The above work perfectly , however if I try to split them :
ENV={'PATH' : os.environ['PATH']}
env=Environment(ENV)
The below error show that the path is not added correctly ...
g++: error: /Fomaino.obj: No such file or director
g++: error: /c: No such file or directory
g++: error: /I.: No such file or directory
It does not work ? I have even try the following :
env=Environment()
env['PATH']= os.environ['PATH']
same error
g++: error: /Fomaino.obj: No such file or director
g++: error: /c: No such file or directory
g++: error: /I.: No such file or directory
I try to use the following in SCONS user guide
env['ENV']['PATH'] = 'C:/cygwin/bin'
also fails.
I already have an working approach , but i am curious why the other two approach fails which i think in term of logic they are the same... or I am wrong...
Any additional SCons Environment variables that you want to be set in the Environment should be passed as keyword arguments to the Environment constructor:
Environment(VAR=VALUE)
From the SCons Users Guide:
Environment([key=value, ...]) , env.Environment([key=value, ...])
Return a new construction environment initialized with the specified
key=value pairs.

Settings Bundle in xcode for iphone

I'm trying to set my build version and build date in my app in settings bundle following this tutorial.
But I keep getting this error no matter what:
line 9: File Doesn't Exist, Will Create: /Volumes/Work Invalid
Arguments + 1: syntax error: invalid arithmetic operator (error token
is "'t Exist, Will Create: /Volumes/Work Invalid Arguments + 1")
Command /bin/sh failed with exit code 1
Could somebody please help me....
Thanks in advance.
Ok , I found the mistake : when we post, revers quotes are use to formate the message. So, please replace all  by a reverse quote `
echo "#define BUILD_DATE #\"date "+%d/%m/%Y %H:%M"\"" > build.h
build, and check your build.h
My solution is to create a build.h header with the build date (build version is related to build date), and use this from my app to display the App version + build date.
Of course, build.h need to be refresh each time you build your App.
So, here is how I do this :
Select your Targets (where you can set Bundle ID ...) / Build Phases. Go to menu Editor/Add Build Phase/Add Run Script Build Phase. Move the new created line (Run Script) up to the line "Compile sources" (use drag&drop).
open the line "Run script", and replace Type a script... with :
echo "#define BUILD_DATE #\"date "+%d/%m/%Y %H:%M"\"" > build.h
Now each time you will build, build.h will be re-create.
So, now you need to build => you will have your 1st build.h avail at root of your project.
Add it to your project.
Now, import build.h in the VC where you need the information.
Here is how I use it (I have a iboultet to a label)
- (void)viewDidLoad
{
[super viewDidLoad];
//cf http://stackoverflow.com/questions/3015796/how-to-programmatically-display-version-of-target-in-iphone-app-xcode
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleShortVersionString"];
self.version.text = [NSString stringWithFormat:#"v %# %#", appVersionString,BUILD_DATE];
}

Using gtest in jenkins

I successfully run my unit test with google test in Jenkins, but I don't know how to show the .xml file generated by gtest. It is said that gtest satisfies the JUnit format, so what I set is as follows:
But it ends up with errors after a building.
No test report files were found. Configuration error?
Build step 'Publish JUnit test result report' changed build result to FAILURE
Finished: FAILURE
Fraser's answer is good and you need some extra processing to convert the gtest XML to proper JTest format.
First you ask gtest to output the result to XML using:
mygtestapp --gtest_output=xml:gtestresults.xml
Then in a script you need to add extra elements to properly flag skipped tests as such. Jenkin's JTest processor requires that a skipped test contains the <skipped> element and not just setting status to "notrun":
awk '{ if ($1 == "<testcase" && match($0, "notrun")) print substr($0,0,length($0)-2) "><skipped/></testcase>"; else print $0;}' gtestresults.xml > gtestresults-skipped.xml
mv gtestresults.xml gtestresults.off
If running this on a windows batch file, put the awk action inside a file to avoid problems with the quotes. awk.progfile:
{ if ($1 == "<testcase" && match($0, "notrun")) print substr($0,0,length($0)-2) "><skipped/></testcase>"; else print $0;}
And create add in your bat file:
awk -f awk.progfile gtestresults.xml > gtestresults-skipped.xml
Lastly you point the JTest processor as a Post-Build step to read the converted XML:
# Publish JUnit Test Result Report
Test Report XMLs: gtestresults-skipped.xml
Are you running your test executable with the correct flags (i.e. --gtest_output=xml[:DIRECTORY_PATH\|:FILE_PATH])?
From the --help output:
--gtest_output=xml[:DIRECTORY_PATH\|:FILE_PATH]
Generate an XML report in the given directory or with the given file
name. FILE_PATH defaults to test_details.xml.
The error on the Jenkins configuration page is a bit of a red herring.
Essentially, what's happening is that the test report xml file hasn't been generated by the build job. So, you then get this error:
Recording test results
No test report files were found. Configuration error?
Of course, the location must be configured correctly. For that, see this post:
How to configure test-reports on Jenkins CI working with grails?
So, how to fix the error? The key is to study the console output to check whether the tests did successfully run. Chances are they didn't, and that's why the error has happened.
Once you get the tests running successfully, assuming that you correctly configured the location, you should be ok.
You're using JUnit so it'll be a Java project. I'll note here in case it may help others, that we were running Xcode. The tests weren't being run.
Buried in Jenkins console output just above the error was this note:
note: RunUnitTests exited without running tests because TEST_AFTER_BUILD was set to NO.
Popping back into Xcode, and setting the UnitTests target's Test After Build flag to YES did the trick. That's under the Unit Testing section. You can also of course set the flag at the Project level, and change the target's to 'Other', setting a value of $(inherited).
Your results file is not stored at correct location and Jenkins plugin cannot find it. After your tests are executed and XML file is generated do you store it anywhere?
I suggest try make it working by replacing result.xml with '*' (assuming this is the only XML file that is supposed to be stored there) and if this is going to work then start working on correct file name.
We had the same issue in our configuration. Making sure that generated result XML is stored where the plugin expect it was the key. You can determine workspace root from your project config.
Jenkins has xunit plugin that converts googletest xml to junit format: https://plugins.jenkins.io/xunit/.
Example of pipeline
pipeline {
agent any
stages {
stage('Test'){
steps {
sh "run_tests.bash"
}
}
}
post {
always{
xunit (
thresholds: [ skipped(failureThreshold: '0'), failed(failureThreshold: '0') ],
tools: [ GoogleTest(pattern: 'reports/*.xml') ]
)
}
}
}
Other useful links:
https://jenkins.io/doc/pipeline/steps/xunit/
https://jenkins.io/blog/2016/10/31/xunit-reporting/
Here is a windows batch version for converting the google-test "notRun" to junit "skipped" via windows batch. I know that there are more elegant ways, but this one only requires windows batch and does the job
rem convert gtest xml to junit compatible format (replace notRun by skipped)
IF EXIST %INTEXTFILE% (
IF EXIST %OUTTEXTFILE% (
del %OUTTEXTFILE%
waitfor fileSystemToDoItsStuff /t 1
)
FOR /f "tokens=1,* delims=¶" %%A IN ( '"type %INTEXTFILE%"') DO (
ECHO."%%A" | findstr /C:"DISABLED_">nul & IF ERRORLEVEL 1 (
SET modified=%%A
) ELSE (
SET string=%%A
SET modified=!string:/^>=^>^<skipped /^>^</testcase^>!
)
ECHO !modified!>> %OUTTEXTFILE%
)
del %INTEXTFILE%
waitfor fileSystemToDoItsStuff /t 1
move %OUTTEXTFILE% %INTEXTFILE%
)

Resources