Passing global envvar JAVA_HOME to builds through jenkins.war - linux

I administrate a jenkins instance on Linux.
I have been asked to pass a system-wide JAVA_HOME as a global ENV var for jenkins builds (as opposed to just jenkins itself), and I wish to do this through the service/daemon startup script. (Please don't give per-job Jenkinsfile / build pipeline solutions.)
Some plugins like maven-javadoc-plugin apparently require this variable.
(Curiously, this was never before necessary for the existing builds on this jenkins install. Either the used plugins changed, or jenkins did? Since I don't build on this, I can't say which.)
The only way I managed to do make this work for now, is using a fixed string through the GUI at <jenkins-url>/configure under "Global properties > Environment variables".
I understand I can add JDK installations under <jenkins-url>/configureTools/, but this, again, only allows fixed strings, which I can't be bothered to remember correcting on every system update.
What I should be able to do instead, is pass the ENV var to the jenkins service at startup, such as: JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))).
jenkins (debian package) in fact brings an /etc/default/jenkins file,
which says you can pass a --javahome=$JAVA_HOME argument; like this:
/usr/bin/java -jar jenkins.war --javahome=/usr/lib/jvm/java-11-openjdk-amd64
However, this seems incorrect and does not work on current jenkins versions. It throws java.lang.IllegalArgumentException: Unrecognized option: --javahome=/usr/lib/jvm/java-11-openjdk-amd64 at winstone.cmdline.CmdLineParser.parse(CmdLineParser.java:52)
Since some other options uses camelCase (like --httpPort), I have also tried --javaHome=$JAVA_HOME instead.
This option is accepted (jenkins doesn't choke on startup), but it also doesn't work, it appears to get ignored?
I didn't manage to figure out if this should be the correct option from the source code either.
Jenkins version: 2.319
Perhaps someone can tell me if this used to work, is a bug, or how to do this if I'm doing it wrong.

Related

Set linker search path for build in CMake

It seems this question has been asked very often before but none of the solutions seem to apply in my case.
I'm in a CMake/Linux environment and have to run an executable binary during the build step (protoc in particular).
This binary needs a library but it's not installed (and cannot be) in the in the standard directories like /usr, so the library cannot be found.
Unfortunately I cannot manipulate the protoc call because it's embedded in a 3rd party script.
I can now set LD_LIBRARY_PATH before every make or set it system wide but this is very inconvenient especially when it comes to IDEs in which the build takes place or distributed build scenarios with continuous build environments.
I tried to set LD_LIBRARY_PATH via
set(ENV{LD_LIBRARY_PATH} "/path/to/library/dir")
but this seems to have no effect during the build step.
So my question is: can I set a library search path in CMake which is used during the build?
Try this
SET(ENV{LD_LIBRARY_PATH} "/path/to/library/dir:$ENV{LD_LIBRARY_PATH}")
I also used this dirty trick to temporary change some environment variables:
LD_LIBRARY_PATH="/path/to/library/dir:$LD_LIBRARY_PATH" cmake ...
After execution of this line LD_LIBRARY_PATH is not changed in the current shell.
Also, I do not find it bad to change LD_LIBRARY_PATH before invoking cmake:
export LD_LIBRARY_PATH=...
It won't change anything system-wide, but it would be used for your current shell, current build process. The same holds for CI builds. You can save the variable and restore it after cmake invocation:
MY_LD=$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=...
cmake...
export LD_LIBRARY_PATH=$MY_LD
I have recently run into a somewhat similar problem.
My solution was to incorporate sourcing a file that set the appropriate environment into every command.
For example, this custom command:
add_custom_command(
OUTPUT some_output
COMMAND some_command
ARGS some_args
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
)
Would become:
set(my_some_command_with_environment "source my_environment_script.sh && some_command")
add_custom_command(
OUTPUT some_output
COMMAND bash
ARGS -c "${my_some_command_with_environment} some_args"
DEPENDS some_dependencies
COMMENT "Running some_command some_args to produce some_output"
VERBATIM
)
Obviously, this has some disadvantages:
It relies on a bash shell being available.
It sources the environment script for every command invocation (performance issue) and you will have to change all invocations of commands that rely on that environment variables.
It changes the normal syntax of having the command follow COMMAND and the arguments follow ARGS, as now the 'real' command is part of the ARGS.
My CMake-Fu has proven insufficient to find a syntactically nicer way of doing this, but maybe somebody can comment a nicer way.
I had a similar issue for an executable provided by a third party library. The binary was linked against a library not provided by the distribution but the required library was included in the libs directory of the third party library.
So running LD_LIBRARY_PATH=/path/to/thirdparty/lib /path/to/thirdparty/bin/executable worked. But the package config script didn't set up the executable to search /path/to/thirdparty/lib for the runtime dependent so CMake would complain when CMake tried to run the executable.
I got around this by configuring a bootstrap script and replacing the IMPORTED_LOCATION property with the configured bootstrapping script.
_thirdpartyExe.in
#!/bin/bash
LD_LIBRARY_PATH=#_thirdpartyLibs# #_thirdpartyExe_LOCATION# "$#"
CMakeLists.txt
find_package(ThirdPartyLib)
get_target_property(_component ThirdPartyLib::component LOCATION)
get_filename_component(_thirdpartyLibs ${_component} DIRECTORY)
get_target_property(_thirdpartyExe_LOCATION ThirdPartyLib::exe IMPORTED_LOCATION)
configure_file(
${CMAKE_CURRENT_LIST_DIR} _thirdpartyExe.in
${CMAKE_BINARY_DIR}/thirdpartyExeWrapper #ONLY
)
set_target_properties(ThirdPartyLib::exe PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/thirdpartyExeWrapper)
Honestly I view this as a hack and temporary stop gap until I fix the third party library itself. But as far as I've tried this seems to work on all the IDE's I've thrown at it, Eclipse, VSCode, Ninja, QtCreator, ... etc

Run from clean login shell without credentials

So I've got an executable with conflicting dependencies with the build system it is running in. (AKA Xilinx doesn't play well with others). I'd love to run a cmake script as part of the build process, but it is depended on different dlls. I can try to figure out a version of cmake that matches the xylinx dlls. Xylinx redirects the dependencies to the different C++ runtimes by setting a bunch of environment variables.
Sanitize environment with command or bash script?
Will completely clean out all environments, but what i really want to do is run the script after the .bash_rc or .bash_profile is called. (cmake seems to require some of that to be set, as env -i cmake returns an error) I'd like to do it without having to require the login credentials. Is that possible?
You can pass environment variables directly in a command line, right before the executable name:
ENV_VAR=foo command -options ...
If you want to pass multiple variables just add them one after one:
ENV_VAR_FOO=foo ENV_VAR_BAR=bar command -options ...
In your case, you'll need to find out which environment variable cmake needs to access the libraries. Then pass this to the call, like:
LIB_PATH=/path/to/libs cmake -options ...

qmake -query internal settings in Linux - where are they?

I am building a Linux system with cross-compiler using ptxdist. It allows me to configure Qt4 for installation and it builds and installs qt-everywhere-opensource-src-4.6.3 Ok. However, the qmake internal settings are screwed up and I don't know how to fix them.
When I run qmake -query I get:
me#ubuntu:~$ qmake -query
QT_INSTALL_PREFIX:/
QT_INSTALL_DATA:/
QT_INSTALL_DOCS://doc
QT_INSTALL_HEADERS://include
QT_INSTALL_LIBS://lib
QT_INSTALL_BINS://bin
QT_INSTALL_PLUGINS://plugins
QT_INSTALL_TRANSLATIONS://translations
QT_INSTALL_CONFIGURATION:/etc/xdg
QT_INSTALL_EXAMPLES://examples
QT_INSTALL_DEMOS://demos
QMAKE_MKSPECS://mkspecs
QMAKE_VERSION:2.01a
QT_VERSION:4.6.3
Through some research, it looks like this can be fixed by simply rebuilding Qt, but it's not fixing this problem. I dug into the build output a bit and it looks like the ./configure command for the Qt build has "-prefix /usr" so I don't know why this isn't being fixed.
I would like to fix these internal values manually if possible because the Qt build takes hours. Does anyone know how to do this?
At configure time these paths are hardcoded in 'src/corelib/global/qconfig.cpp', and end up hardcoded into qmake when it is built. They are also hardcoded into many other files, like all the .la and .pc files, not to mention the Makefile install rules.
The only way to fix this is to figure out why configure keeps screwing up the prefix. configure is a big shell script, so it's easy to see where $QT_INSTALL_PREFIX is assigned from the '-prefix' argument, and then the different checks that are done on it (like running it through 'config.tests/unix/makeabs'). Try putting print statements before/after $QT_INSTALL_PREFIX is changed, and you should be able to find out where the path gets screwed up.
Also, you don't have to wait for the full build to complete to tell if the prefix was set
correctly. After configure runs, take a look in 'src/corelib/global/qconfig.cpp' and see what 'qt_configure_prefix_path_str' is set to.
You can manually set these properties using
qmake -set VARIABLE VALUE
They are stored using QSettings, the Qt built-in persistent applications settings.
see Configuring qmake's Environment
Configure scripts can be fuzzy about slashes. Are you sure that the build prefix is /usr and not /usr/ .

Ant build in linux

I'm trying to run an ant build in linux and I'm getting odd results. I can't seem to get anything to run without specifying each and every library on the classpath, so I systematically added every jar in the "lib" and "ant/dep/lib" locations to the classpath explicitly.
It runs a bit without any issues (it's a setup batch, so in the first phase of the script, it uses a lot of "input" tasks), then I receive the message that org.apache.tools.ant.taskdefs.optional.PropertyFile was not found. Looking around, I discovered it was located in ant-nodeps.jar and I had added it to the class path, but no change.
Complete failure due to missing libraries I can understand, but why would the build partially function if I was sure I was including every library (including ant-nodeps.jar)?
The script file to launch it is as follows:
#!/QOpenSys/usr/bin/bsh
ANT_HOME=dep/ant
PARAMS="-Dant.home=$ANT_HOME -Dsystem.type=as400 -Dis-as400=y"
LIBS="lib/ant-contrib-1.0b3.jar:lib/ant-launcher.jar:lib/ant.jar:lib/catalina-ant.jar:lib/catalina-deployer.jar:lib/commons-net-2.2.jar:lib/el-api.jar:lib/ganymed.jar:lib/jakarta-oro-2.0.8.jar:lib/jasper-el.jar:lib/jasper.jar:lib/jsp-api.jar:lib/log4j-1.2.16.jar:lib/mail.jar"
ANTLIBS="$ANT_HOME/lib/ant-antlr.jar:$ANT_HOME/lib/ant-jai.jar:$ANT_HOME/lib/ant-starteam.jar:$ANT_HOME/lib/ant-apache-bcel.jar:$ANT_HOME/lib/ant-javamail.jar:$ANT_HOME/lib/ant-stylebook.jar:$ANT_HOME/lib/ant-apache-bsf.jar:$ANT_HOME/lib/ant-jdepend.jar:$ANT_HOME/lib/ant-swing.jar:$ANT_HOME/lib/ant-apache-log4j.jar:$ANT_HOME/lib/ant-jmf.jar:$ANT_HOME/lib/ant-testutil.jar:$ANT_HOME/lib/ant-apache-oro.jar:$ANT_HOME/lib/ant-jsch.jar:$ANT_HOME/lib/ant-trax.jar:$ANT_HOME/lib/ant-apache-regexp.jar:$ANT_HOME/lib/ant-junit.jar:$ANT_HOME/lib/ant-weblogic.jar:$ANT_HOME/lib/ant-apache-resolver.jar:$ANT_HOME/lib/ant-launcher.jar:$ANT_HOME/lib/ant.jar:$ANT_HOME/lib/ant-commons-logging.jar:$ANT_HOME/lib/ant-netrexx.jar:$ANT_HOME/lib/xercesImpl.jar:$ANT_HOME/lib/ant-commons-net.jar:$ANT_HOME/lib/ant-nodeps.jar:$ANT_HOME/lib/xml-apis.jar"
java -classpath $LIBS:$ANTLIBS $PARAMS org.apache.tools.ant.launch.Launcher -buildfile install/install.xml
Any help would be appreciated, even if only suggestions for what to try.
EDIT: In light of oers observation, I realized that there are shell scripts for ant afterall (have pity, I'm no expert in linux), so I'm going to attempt to use it to launch ant rather than try to do the same thing myself. I'll let everyone know of my progress and/or if I was able to fix it doing it that way.
I looked into the shellscript on my machine.
There is an additional parameter set:
-Dant.library.dir=\"$ANT_LIB\"
Perhaps this is needed?
ant_exec_command="exec \"$JAVACMD\" $ANT_OPTS
-classpath \"$LOCALCLASSPATH\"
-Dant.home=\"$ANT_HOME\"
-Dant.library.dir=\"$ANT_LIB\" $ant_sys_opts
org.apache.tools.ant.launch.Launcher
$ANT_ARGS
-cp \"$CLASSPATH\"
$ant_exec_args"
Using the ant scripts to launch the setup seemed to do the trick, specifying parameter -lib as lib and -buildfile as install/install.xml.

How do I pass an environment variable to a Netbeans Makefile on Ubuntu?

I'm using Netbeans on Linux (Ubuntu 9.04) to build a C project.
How do I pass in an environment variable so that's it's visible to the Makefile?
If I do a normal export MYVAR="xyz" and then run make from the command line this works fine of course.
But Netbeans doesn't seems to use the .bashrc environment, so if I click "build" in Netbeans, the make fails.
Interestingly, the problem doesn't seem to occur on MacOSX - I've added the variable to ~/.MacOSX/environment.plist, and that value is visible to Netbeans.
I found this post which suggested modifying ~/netbeans-6.8/etc/netbeans.conf. I've tried this, by adding -J-DMYVAR=xyz to the end of netbeans_default_options, ie:
netbeans_default_options="-J-client -J-Xverify:none -J-Xss2m -J-Xms32m -J-XX:PermSize=32m -J-XX:MaxPermSize=200m -J-Dapple.laf.useScreenMenuBar=true -J-Dsun.java2d.noddraw=true -J-DMYVAR=xyz"
But this didn't seem to work.
Edit:
This answer is possibly not valid for Unity-based flavours of Ubuntu.
The issue is actually nothing to do with NetBeans - it's related to the Ubuntu (ie Gnome) Launcher.
As this blog post explains, you need to add variables to the rather obscure ~/.gnomerc (No Mercy? :) file in order for them to be passed to applications started with Launcher!
So just edit ~/.gnomerc and add the variables as you would to ~/.bashrc, eg:
export MYVAR="xyz"
and logout/login.

Resources