How to alias a particular cmake command - bash

I'm trying to work around a QtCreator bug (https://bugreports.qt.io/browse/QTCREATORBUG-20972) where QtCreator fails to open a CMake project because it is trying to create a socket file in /tmp/RANDOM_PATH/socket whereas "RANDOM_PATH" does not exist.
I can reproduce the issue manually with:
$ /usr/bin/cmake -E server --pipe=/tmp/not-existing-path/socket
--experimental CMake Error: Internal Error with /tmp/not-existing-path/socket: EACCES
The suggestion given in https://bugreports.qt.io/browse/QTCREATORBUG-18444 is to create an alias of cmake which would report
"serverMode":false
when given the command
cmake -E capabilities
which on my machine (Ubuntu 18.04) outputs:
{"generators":[{"extraGenerators":[],"name":"Watcom WMake","platformSupport":false,"toolsetSupport":false},{"extraGenerators":["CodeBlocks","CodeLite","Sublime Text 2","Kate","Eclipse CDT4","KDevelop3"],"name":"Unix Makefiles","platformSupport":false,"toolsetSupport":false},{"extraGenerators":["CodeBlocks","CodeLite","Sublime Text 2","Kate","Eclipse CDT4"],"name":"Ninja","platformSupport":false,"toolsetSupport":false}],"serverMode":true,"version":{"isDirty":false,"major":3,"minor":10,"patch":2,"string":"3.10.2","suffix":""}}
What's the easiest way to achieve this?
I've tried to add such an alias:
cmake='cmake | sed "s/\"serverMode\":true/\"serverMode\":false/g"'
, but the issue is that the "sed" command needs to be after the arguments given to cmake, and not before.

I see from that bug report:
If you want to run a newer cmake without server-mode, then you will need to write a wrapper around cmake that removes the server-mode support indicator from the output reported by
cmake -E capabilities
That would be something like
cmake() {
if [[ "$*" == "-E capabilities" ]]; then
command cmake "$#" | jq -c 'del(.serverMode)'
else
command cmake "$#"
fi
}
You make have to make that a standalone script rather than a shell function.

Related

How to get CMake variable of package in shellscript

I want to find the Qt5WaylandClient_PRIVATE_INCLUDE_DIRS variable which is set by the Qt5WaylandClient package. How can I get it from the shell (dash)? Something like this:
cmake -find_package(Qt5WaylandClient) -get_variable Qt5WaylandClient_PRIVATE_INCLUDE_DIRS
or
cmake -file path/to/my/CMakeLists.txt -get_variable Qt5WaylandClient_PRIVATE_INCLUDE_DIRS
CMake does have a --find-package command line option, but it is not well supported, nor well-documented. There is an answer describing its functionality here, but that's probably not what you're looking for.
Initially, it appears you could just run cmake in script mode, using -P, on a CMake file containing your find_package(Qt5WaylandCleint) command and print its variables to the console.
cmake -P MyFindQt5WaylandClient.cmake
However, running find_package() outside the confines of a CMake project does not work. It yields several errors because CMake doesn't know anything about the system or your target language. So, you must create a minimal CMake project, then run find_package(). Something like this CMakeLists.txt file should work:
cmake_minimum_required(VERSION 3.16)
project(MyProj)
find_package(Qt5WaylandClient REQUIRED)
# Print the desired variable.
message("${Qt5WaylandClient_PRIVATE_INCLUDE_DIRS}")
You can then run cmake from the command line, and this will print the Qt5WaylandClient_PRIVATE_INCLUDE_DIRS variable to the console. You can use the -S and -B command line options to specify the CMake source and binary directories, respectively.
cmake -S . -B build

How to do dry run with CMake?

With GNU make, a dry run can be performed via
make -n
Is there a similar option for CMake? The best I could come up with is
cmake ..
make -n | grep -vi cmake
However, I am being too restrictive and am wondering if there is an easier way to achieve this.
According to the command line syntax, if you use -- on the command line with cmake, the parameters following that are passed directly to the native build tool. Eg. what you did is somewhat equivalent to this:
cmake ..
cmake --build -- -n

figure out ld command arguments from xcode run script build phase

How can I determine what will be the arguments of the ld command in the build process from inside a script running as "run script build phase"?
I was looking at xcodebuild -dry-run as an option, but then I need to understand what should be the arguments I supply it.
Any idea for a robust solution?
EDIT:
It seems that xcodebuild doesn't support LD and LDPLUSPLUS when the project includes swift source code. So the solution that #fpotter offered doesn't work on project with swift.
Any thoughts?
Xcode doesn't expose a nice way to do this. In a Run Script build phase, all you have to work with are the Xcode build settings provided to you in the environment.
If you really need the entire argument list to ld, there's a hack you can use. With the LD and LDPLUSPLUS build settings, you can make Xcode call a script of your own instead of the real ld. From that script, you could capture the args, call through to the real linker, and then do whatever post processing you like there rather than in a Run Script build phase.
Here's how you could do that:
Create an .xcconfig for your target.
It should look like this:
LD = $(SRCROOT)/ld-wrapper/clang
LDPLUSPLUS = $(SRCROOT)/ld-wrapper/clang++
SRCROOT points to your project's directory. The LDPLUSPLUS line is only required if your app has C++ or ObjC++ code. If you don't want to create an xcconfig, you can also add these as User-Defined build settings via the Xcode UI.
Create wrapper scripts for Xcode to call.
Install a script like this at <your project root>/ld-wrapper/wrapper.sh:
#!/bin/bash
set -o errexit
# Choose which clang to run (clang or clang++) depending on how we're invoked.
# If we're invoked via the 'clang' link, we'll run 'clang'. If we're invoked
# via the 'clang++' link, we'll run 'clang++'.
CLANG_PATH="$DEVELOPER_DIR"/Toolchains/XcodeDefault.xctoolchain/usr/bin/$(basename "$0")
"$CLANG_PATH" "$#"
echo "clang args: $#"
echo "do any post processing here."
Create symlinks for the wrapper script for clang and clang++:
cd <project root>/ld-wrapper
ln -s wrapper.sh clang
ln -s wrapper.sh clang++
That's it. It's ugly, but it works.

gfortran include path -- is there an alternative to passing multiple -I options?

I have some Fortran code which uses included modules, and I am wondering what environment variables actually work to set the include path.
To test this out I've been using one of the NAG example codes.
This works:
$ gfortran e04ucfe.f90 -lnag_nag -I/opt/NAG/fll6a23dfl/nag_interface_blocks
This doesn't work:
$ export CPATH=/opt/NAG/fll6a23dfl/nag_interface_blocks
$ gfortran e04ucfe.f90 -lnag_nag
e04ucfe.f90:10.37:
USE nag_library, ONLY : nag_wp
1
Fatal Error: Can't open module file 'nag_library.mod' for reading at (1): No such file or directory
However, the GCC/GFortran documentation states that:
The gfortran compiler currently does not make use of any environment
variables to control its operation above and beyond those that affect
the operation of gcc.
(see https://gcc.gnu.org/onlinedocs/gfortran/Environment-Variables.html and https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html#Environment-Variables)
I've tried ltrace-ing the gfortran run and can see it looking at other environment variables (e.g. the regular PATH) but not CPATH.
I can work around this with this:
gfortran e04ucfe.f90 -lnag_nag `echo -I$CPATH | sed -e 's/:/ -I/'`
...but why is this necessary? CPATH works fine with gcc, including for other languages than C/C++, so why doesn't this work with gfortran?
Is there something I can successfully use to the same effect as CPATH for gcc with gfortran, to avoid having to pass multiple -I arguments?
Side note: LIBRARY_PATH works fine in a similar way, for replacing the -L/path/to/libs on the gfortran command-line.
As far as I know gfortran does not support this, which is quite annoying. But it is possible to work around it. If you name the following script gfortran and put it in a directory in your $PATH that is searched before the one with the real gfortran in it, then you will have the behavior you want, with $CPATH transparently being expanded into -I arguments:
#!/bin/bash
/path/to/gfortran $(for i in ${CPATH//:/ }; do echo -I"$i"; done) "$#"
Remember to mark it as executable. For example, if my $PATH is /home/amaurea/local/bin:/usr/local/bin:/usr/bin:/bin and gfortran lives in /usr/local/bin, I would set it up as
$ cd /home/amaurea/local/bin
$ cat <<HERE > gfortran
#!/bin/bash
/usr/bin/gfortran $(for i in ${CPATH//:/ }; do echo -I"$i"; done) "$#"
HERE
$ chmod a+x gfortran
Alternatively you can formulate it as a shell alias, but that would be less flexible and will not work in as many situations.
If you are using Makefiles, I got this to work using the subst command. This replaces the : with -I for each path in the file.
usr/bin/gfortran e04ucfe.f90 -lnag_nag -I${subst :, -I,$(CPATH)}

command line IntelliJ on Mac OS X

I'm trying to launch IntelliJ on command line in Mac OS X to use it's diff tool. Theoretically idea.sh diff file1 file2 should work. In practice there are some issues with the file which I think I worked around (removing some arguments to readlink etc).
However when it does start, it wants me to enter license information (even though an instance of Intellij is already running and the license is there). Which leads me to believe that there is some sort of separation of command line world vs non-command line world on Mac OS X? IS that true?
Also when I select 30 days eval it proceeds to give me the following exception:
java.lang.IllegalArgumentException: Argument 0 for #NotNull parameter of com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.getProviders must not be null
at com.intellij.openapi.fileEditor.impl.FileEditorProviderManagerImpl.getProviders(FileEditorProviderManagerImpl.java)
at com.intellij.openapi.diff.impl.highlighting.EditorPlaceHolder.setContent(EditorPlaceHolder.java:73)
at com.intellij.openapi.diff.impl.highlighting.DiffPanelState$1.run(DiffPanelState.java:38)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:864)
...
IntelliJ can install a command line launcher for you, adding it to a PATH directory would make it as any other commands on the system. The command is "idea".
Try running /Applications/IntelliJ\ IDEA.app/Contents/MacOS/idea instead. idea.sh is not designed for Mac and will not work without some manual changes.
Another option is to create the command line launcher: Tools | Create Command-line Launcher.
If you are using Toolbox, it provides the way to create the command launcher automatically.
Try:
Tools > Create Commandline Launcher
This will create a command line launcher.
After that you can launch IntelliJ from your desired folder like with a command like this :
idea .
or
idea <path to the folder>
First step, you'll follow and click the menu, Tools > Create Commandline Launcher you'll run this command on what you want open project's directory.
idea .
Idea expects paths to be fully qualified, so I wrote a small helper script. Invoke like:
$ idiff foo.txt bar.txt
The code for idiff:
#!/bin/bash
idea='/Applications/IntelliJ IDEA 10.app/Contents/MacOS/idea'
left=`abspath $1`
right=`abspath $2`
"$idea" diff $left $right
There is probably a real abspath tool somewhere, but I have a simple hand-rolled one:
$ cat `which abspath`
#!/bin/bash
ORIG_DIR=`pwd`
for fn in $* ; do
if [ -e $fn ]; then
d=`dirname $fn`
if [ -z $d ]; then
echo `pwd`/$fn
else
cd $d
echo `pwd`"/"`basename $fn`
fi
else
echo "Don't know how to process $fn" 1>&2
exit 1
fi
cd $ORIG_DIR
done
If you have the toolbox installed, this is now controlled using the Toolbox App Settings.
First enable using the (global) toolbox app settings:
Now, you can enable at the IDE level (here using Intellij):
First you must create the shell scripts to open the IDEs, in the latest version it's done on the Toolbox
Toolbox App > Configuration > Settings > Generate shell script > export to a folder like /User/asilva/IDEs
Then you could call it like ./User/asilva/IDEs/idea or ./User/asilva/IDEs/webstorm
But if you want to call it without the absolute path, the it's needed to add it on the $PATH to be loaded every time the terminal is open:
~/.zshrc
(...)
# idea + webstorm
export PATH="/Users/asilva/IDEs:$PATH"
with this, the webstorm or idea command will be globally available

Resources