run a "source" bash shell script in qmake - qt

I want to use the intel compiler for Qt, but using the intel compiler implies running the script
$ source /opt/intel/bin/compilervars.sh intel64
Of course, I could add this to ~/.bashrc, but this would not run it in QtCreator, where it still complains about missing icpc. So I want it to be a part of the main mkspec qmake file.
How can I execute that full bash command in qmake?

Short Answer: Using QMAKE_EXTRA_TARGETS and PRE_TARGET_DEPS, you can execute source /opt/intel/bin/compilersvars.sh intel64, but simply sourcing them will not solve your issue.
Long Answer: The QMake file is converted into a Makefile. Make then executes the Makefile. The problem you will run into is that Make executes each command in its own shell. Thus, simply sourcing the script will only affect one command, the command that executes the script.
There are a couple of possible ways to make things work:
Execute the script before starting Qt-Creator. I've actually done this for some projects where I needed to have special environment variables setup. To make my life easier, I created a shell command to setup the environment and then launch Qt-Creator.
Within Qt-Creator, modify the Build Environment for the project I've also used this trick. In your case, simply look at the environment setup by the script and change the "Build Environment" settings under the project tab for your project to match those setup by the script.
It might also be possible to modify QMake's compiler commands, but I am not sure you can make it execute two commands instead of one (source the script then execute the compiler). Further more, this will make the project very un-transportable to other systems.

You can create a shell script that does more or less the following:
#! /usr/bin/env sh
# Remove the script's path from the PATH variable to avoid recursive calls
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export PATH=${PATH/$SCRIPT_DIR:/}
# Set the environment up
source /opt/intel/bin/compilervars.sh intel64
# Call make with the given arguments
make "$#"
Save it into a file named "make" in an empty directory somewhere, make it executable, then change the build environment in QT Creator to prepend PATH with the script's directory:
PATH=[dir-of-make-script]:${Env:PATH}
You can do this either in the project settings or once and for all in the kit settings.
Like this, QT Creator will be fooled into calling your make script which sets up your environment before calling the actual make binary. I use a similar technique under Windows with Linux cross-toolchains and it has been working well so far.

Related

Can I use zsh as the default non-interactive shell for WSL2 Ubuntu?

I am trying to use Run/Debug Configurations on WebStorm, however it doesn't seem to source .zshrc and produces errors about not finding commands and environment variables. (An example of this would be yarn tauri dev when using Tauri)
I have installed Ubuntu 20.04 in WSL and the project I opened in WebStorm resides under the $HOME directory. WebStorm is installed in Windows.
For the interactive shell, I have made zsh the default by chsh -s $(which zsh), but when using Run/Debug Configurations it uses the default non-interactive shell, which is dash as far as I know. And my environment variables and PATH are all set in .zshrc, which is not sourced by dash.
It seems in CLion, it is possible to execute commands in the login shell according to this YouTrack issue, but such an option is not available on WebStorm.
Is it possible to use zsh instead of dash as the default non-interactive shell? If not, it would help me a lot to know what is the best practice in such situations.
There are several questions and points you make:
First, from the question title (and the summary at the end):
Can I use zsh as the default non-interactive shell for WSL2 Ubuntu?
Well, maybe (using symlinks), but it would be a really bad idea. So many built-in scripts rely on /bin/sh pointing to Dash, or at least Bash. While Zsh might be compatible with 99.9% of them, eventually there's a strong likelihood that some difference in Zsh would cause a system-level script to fail (or at least produce results inconsistent with those from Dash).
It is possible in Ubuntu to change the default non-interactive ("system" shell) from Dash to Bash with sudo dpkg-reconfigure dash. If you select "No" in the resulting dialog, then the system will be updated to point /bin/sh to bash instead of dash.
But not to Zsh, no.
when using Run/Debug Configurations it uses the default non-interactive shell, which is dash as far as I know
I don't run WebStorm myself, so I'm not sure on this exactly. Maybe #lena's answer (or another) will cover it for you, but if it doesn't, I'm noticing this doc page. It might be worth trying to specify Zsh in those settings, but again, I can't be sure.
And my environment variables and PATH are all set in .zshrc, which is not sourced by dash.
Hmm. I'm guessing you would need these set in a .profile/.zprofile equivalent regardless. I would assume that WebStorm is executing the shell as a non-interactive one, which means that it wouldn't even parse ~/.bashrc if Bash was your default shell.
... it would help me a lot to know what is the best practice in such situations.
Best practice is probably to make sure that your ~/.profile has any environment changes needed. Yes, this violates DRY (don't repeat yourself), but it's probably the best route.
Thanks to the answer here and the discussion below, I was able to figure it out. (Thank you, #NotTheDr01ds and #lena.)
The main problem is that WebStorm is installed on Windows and therefore knows only the environment variables in Windows. There are two ways to solve the problem as follows.
Sharing WSL's environment variable to Windows through WSLENV
Add the line below to .zshrc so that it sets $WSLENV when zsh starts.
export WSLENV=VAR_I_WANT_TO_SHARE:$WSLENV
# Don't forget to insert the colon
# And for some reason, appending the variable after $WSLENV didn't work well
In Windows, run
wsl -e zsh -lic powershell.exe
This runs WSL using zsh (logged-in and interactive), then runs powershell which brings you back to Windows. Although this doesn't seem to achieve anything, by going through zsh in WSL, .zshrc was sourced and therefore $WSLENV set as well. You can check if it worked well by running the below command after you've run the above.
$env:VAR_I_WANT_TO_SHARE
Run WebStorm from the PowerShell that was just created.
& 'C:\Program Files (x86)\JetBrains\WebStorm 2022.1.3\bin\webstorm64.exe'
When you run or debug any of the Run/Debug Configurations, you will see that the environment variable is shared successfully.
Setting the PATH in Windows
For most environment variables, the previous method works well. However, PATH is an exception. The Windows PATH is shared to WSL by default. The opposite doesn't work, probably because the PATH in WSL should not interfere with Windows.I've tried adding the $PATH of WSL into $WSLENV but it didn't seem to work.
In the end, what I did was manually adding each needed $PATH of WSL into the Windows PATH.
For example, if there was export PATH=$PATH:home/(username)/.cargo/bin in .zshrc, you can then add \\wsl$\Ubuntu\home\(username)\.cargo\bin to the Windows $env:Path using the Environment Variable window.
I might have made some mistakes, so feel free to leave an edit or comments.
You can try using npm config set script-shell command to set the shell for your scripts. Like npm config set script-shell "/usr/bin/zsh".
When npm run <script name> spawns a child process, the SHELL being used depends on NPM environment. Cм https://docs.npmjs.com/cli/run-script:
The actual shell your script is run within is platform dependent. By
default, on Unix-like systems it is the /bin/sh command, on Windows it
is the cmd.exe. The actual shell referred to by /bin/sh also depends
on the system. As of npm#5.1.0 you can customize the shell with the
script-shell configuration
See also https://github.com/npm/npm-lifecycle/blob/10c0c08fc25fea3c18c7c030d4618a401963355a/index.js#L293-L304

qmake touch function on windows

The qmake manual documents a touch function to update the time stamp of a file, see: touch(filename, reference_filename). It is recommended here to update the timestamp on a file, e.g.:
version.commands = touch $$version.target
Note: the qmake manual documents two parameters, e.g.:
version.commands = touch $$version.target $$version.depends
However, I can't get the touch function to work on Windows using either call. I suspect that qmake is simply calling the linux touch command, since it works fine on Fedora 23.
A workaround is to create a touch.cmd command file on Windows, e.g.:
#COPY /B %1+,, %1
and use the following in the .pro file:
version.commands = $$system(touch $$version.target)
But I would prefer to use the qmake touch function...
What is the correct way to invoke it in a .pro file so that it works on Windows?
In using qmake, it's critical to remember what things are happening on invocation of qmake and what's happening during the subsequent make/nmake call.
Anything that's specified after version.commands = is going to be executed when make gets invoked.
On the other hand, touch() is a qmake function that will get invoked when you run qmake.
Looking in the Qt source code dev branch as of today, there are just 4 uses of touch() within Qt itself, all in the qtbase/mkspecs/features directory, and none in the context of a .commands construct.

Can not call 'make clean' in cmd regarding qmake project

I'm reading Foundations of Qt Development - by Johan Thelin.
Here quote from page 450 about Building QMake Project.
If you choose to create a Makefile using QMake, you can build your project using a simple make command (or nmake if you’re using Visual Studio). You can clean up your intermediate files using make clean. The slightly more brutal step is to run make distclean, which cleans up all generated files, including the Makefile. You will have to run QMake again to get a Makefile for make.
I tried hard to clean the files using 'make clean'. But cmd displaying the message 'make' is not recognized as an internal or external command, operable program or batch file.
I searched here and tried to find the PATH to make inside Qt directory. But not successful. Then according to this solution I tried to use mingw32-make also. But same results.
Anyone of you can help me?
If you using mingw32, try mingw32-make clean. Remember, you must add mingw's bin directory to User Enviroment to use this command. Follow "My Computer" > "Properties" > "Advanced" > "Environment Variables" > "Path" and add ;C:\Qt\Tools\mingw492_32\bin
OR
use command: setx PATH %PATH%;C:\Qt\Tools\mingw492_32\bin

How to run initialize commands in Octave?

How do you set up Octave software to run initialization commands when it starts? For example, set the prompt (PS1) and cd to the project directory?
Thanks.
I have Octave installed in C:\Octave, so I did what you ask in file at location C:\Octave\3.2.4_gcc-4.4.0\share\octave\site\m\startup. File is called System-wide startup file for Octave and code I put in there is:
PS1('>> ');
addpath('{$path-to-my-octave-files}');
But any code is OK, I guess.
You could
write a script that does the start up routines you want and call octave afterwards
use
octave --persist --eval 'some_code_to_evaluate'
or
set the exec path with
octave --exec-path path_to_your_subprogramms
Personally, I wouldn't want octave to cd to the project directory, since projects directories can change. Furthermore, other features like the --eval command are not that easy to use anymore if you always have some default code running beforehand.

"exec source <script>" does not work in tcl

I'm trying to call a script in Tcl with the command:
exec source <script path>
and I get the error
couldn't execute "source": no such file or directory
How can I call another script from tcl?
Edit: I am running a command I got from another person in my office. I was instructed to run "source " explicitly with source. So in other words, how would I run any command that would work in cshell, in Tcl?
If the script you were given is a cshell script, you can exec it like this:
exec /bin/csh $path_to_script
In effect, this is what the 'source' command does from within an interactive shell. It's not clear whether this is really what you want to do or not (not exactly, but close enough for this discussion).
The reason you can't exec the source command is that exec will only work on executable files (hence the name 'exec'). The source command isn't implemented as an exectuable file, it is a command built-in to the shell. Thus, it can't be exec'd.
If you really feel the need to exec the source command or any other built-in command you can do something like this:
exec /bin/csh -c "source $path_to_script"
In the above example you are execing the c shell, and asking it to run the command "source ". For the specific case of the source command, this doesn't really make much sense.
However, I'm not sure any of this will really do what you expect. Usually if someone says "here's some commands, just do 'source ', it usually just defines some aliases and whatnot to be used from within an interactive shell. Those aliases won't work from within Tcl.
source in csh, like . in bash, executes a script without spawning a new process.
The effect is that any variable that is set in that script is available in current csh session.
Actually, source is a built-in command of csh, thus not available from tcl exec, and using exec without source would not give the specific source effect.
There is no simple way to solve your problem.
source load the source file
you should do:
source <script path>
If you want to execute it, then you need to call the main proc.
another option would be to do:
exec [info nameofexecutable] <scritp path>
Some confusion here. exec runs a separate program, possibly with arguments.
source is not a separate program, it is another Tcl command which reads a file of Tcl commands and executes them, but does not pass arguments. If the other script you are trying to call is written to be run on from the command line, it will expect to find its arguments as a list in variable argv. You can fake this by setting argv to the list of arguments before running source, eg.
set argv {first_arg second_arg}
source script_path
Alternatively you could use exec to start a whole separate Tcl executable and pass it the script and arguments:
exec script_path first_arg second_arg
the error speaks for itself. Make sure you give the correct path name, specify full path if necessary. and make sure there is indeed the file exists in that directory
Recently I wanted to set some UNIX environment variables by sourcing a shell script and stumbled across the same problem. I found this simple solution that works perfectly for me:
Just use a little 3-line wrapper script that executes the source command in a UNIX shell before your Tcl script is started.
Example:
#!/bin/csh
source SetMyEnvironment.csh
tclsh MyScript.tcl

Resources