Suppress output from both CMake and make - makefile

I have two bash scripts, ./build.sh and ./patch.sh.
./patch.sh runs 16 patches on a source directory to update it to the latest version.
./build.sh builds this directory with cmake and make, all the while running a spinner to show progress.
The problem is, even when I redirect cmake and make to /dev/null, the output of both commands still shows, so, instead of looking like this:
[insert spinning spinner here]
it looks like this:
|Building librandom.so [100%]
/Complete!
|Installing librandom.so [100%]
\Complete!
[insert still spinning spinner here]
I would like to silence the output of make and cmake in my bash script, so that the spinner can run without other command-line output.
Is there any way to do this?

Related

Makefile Cygwin: mkdir, "The syntax of the command is incorrect."

Running the following Makefile gives an error message
The syntax of the command is incorrect.
This is because the makefile calls mkdir which is a windows command instead of mkdir from Cygwin. Even though I put cygwin path first in the environment variable, it still calls the windows mkdir instead of the Cygwin one. One quick way to fix is to use mkdir.exe. Then the Cygwin one is called. I am looking for a method to call the correct one without changing the Makefile is there any way to tell Makefile which one it should call. Something in the settings?
all:
echo "make started"
mkdir -p test/tmp
echo "make ended"
Output:
C:\Users\me\Desktop\New_folder>make
echo "make started"
"make started"
mkdir -p test/tmp
The syntax of the command is incorrect.
make: *** [all] Error 1
C:\Users\me\Desktop\New_folder>
I am looking for a method to call the correct one without changing the Makefile is there any way to tell Makefile which one it should call. Something in the settings?
It's unclear which setting you're referring to, but the root of the issue is the shell the Makefile is using. It looks like it's getting cmd.exe in your case, so unqualified "mkdir" triggers its builtin. No path search is performed.
You could try to work around that by directing make to use a different shell, something like this:
make SHELL=\path\to\cygwin\bash.exe
or you could launch make from a bash shell in the first place.
Be aware, however, that even if that works, this may not be the last issue you encounter. Makefiles not built with Windows specifically in mind -- which is most of them -- cannot often adapt to the quite different Windows environment. I've had more luck with MinGW in this area, and then with Automake-based makefiles, but it has nevertheless required some special accommodation in makefile sources and in programming-language sources.

How to enable multiline logs instead of single-line progress-logs

Here is a sample output of my cmake:
2017/10/27 07:51:46 Platform overridden to 'RHEL5_64'
-- cmake version: 3.2.3
-- Configuring done
-- Generating done
-- Build files have been written to: /local/home/etc
[3/3] Linking CXX shared library libsample_z.so
The last line actually shows progress (as indicated by [3/3]) and thus overwritten in-place; so I cannot see all the logs (i.e the messages correspond to [1/3] and [2/3]). I want cmake to print all logs to stay on its own line, like:
Linking CXX shared library libsample_x.so
Linking CXX shared library libsample_y.so
Linking CXX shared library libsample_z.so
What can be done in cmake to log like this?
The "problem" with ninja is, that it automatically detects if you are running from a shell where it can replace the progress output in line. And there are - as of October 2017 - no command line switches or environment variables to change this behavior.
Since it checks for the console's output buffer, I found that piping the output on my Windows console somewhere else does show multi-line outputs again. So i used the following pipe command:
cmake -G "Ninja" ..
cmake --build . > CON
NOTE: That will only work if you don't have this call inside a script that needs the stdout output itself again for piping it e.g. into a log file. Meaning the output is no longer on stdout after this pipe command.
Similar to the accept answer, another option is to tick ninja into not seeing the terminal by piping to cat.
ninja | cat -
This will get you multi line output, but you will loose any console coloring as well.
From man ninja:
-v show all command lines while building

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.

Binary fortran file crashes under Make

I have a binary that runs under my default shell.
The binary runs perfectly o.k. with:
./binary input.dat
However, if I put this inside a make file:
SHELL=/bin/bash
runos:
./binary input.dat
The code crashes and leaves me quite helpless.
Here is what I tested so far, everything inside my Make file and in the shell:
ulimit -a: identical.
Set the shell to bash as seen above.
diff of the environment variables in SHELL and Make with:
env | sort > vars.1
inside make
env | sort > vars.2
Then run the binary with the extra variables in Make with the following command:
env SHLVL=2 MAKELEVEL=1 MAKEFLAGS= ./binary input.dat
strace in the shell and inside make:
strace -o debug binary input.dat
The code keeps on crashing in Make, and runs in the shell. I am already thinking to dump Make for my test cases and just write shell scripts. But I am curious to know what is the difference.
The Fortran code (a mix of F77, F90 and F95) was compiled with gfortran-4.4 and the following options:
FFLAGS= -g -fbacktrace
So, the concrete question is, what can I do to make this binary run under make in Debian!?
update:
I just tested again in a CentOS machine (v5.8), The code inside Makefile does not crash (GNU Make version 3.81).
I also tested on my Debian Wheezy and openSUSE 11.4, both with GNU Make version 3.82 - It crashes!
I tested on Debian Squeeze with GNU Make version 3.81, and it does crash. So, I think it is not dependent on the GNU Make version.
error when crashing:
enter timeloop
------------------------------------------------------------------------
timestep: 1 time: 2.500E-02 days delt: 2.500E-02 days
-------------------------------------------
terminated in routine react_snia
maximum number of iterations exceeded
bye now ...
-------------------------------------------
failure in timeloop
no further time step reduction possible
try reducing min. time step, bye now ...
trying to work around 'GNU Make' using 'waf'
It has been a while since I wanted to test waf, so here is another interesting observation:
I wrote a wscript which contains a function:
import os
def run(ctx):
os.system('./binary input.dat')
And waf run runs!
If I changed the run method to:
import subprocess as sp
def run(ctx):
sp.call('./binary input.dat', shell=True)
The binary also works as expected.
So, now I am thinking GNU Make forks a new sub-shell in a way that causes may binary to fail (although, under RHEL 5.8 Make did work).
solution: compile make from sources ...
Read to find out more.
OK, so after being pretty much desperate, I did what I simply should have done before blame make for all my troubles.
I thought the problem is Debian specific. But I am guessing the version in CentOS-5.8 is a patched version, although it says it's v.3.81.
So, for those who wonder my solution was:
wget http://ftp.gnu.org/gnu/make/make-3.82.tar.gz
tar xvzf make-3.82.tar.gz
cd make-3.82
./configure
./build.sh
# copy make to the directory with the binary and input and run the local make version
./make
# everything works as expected !!!
I thought let's narrow it down -
wget http://ftp.gnu.org/gnu/make/make-3.80.tar.gz
tar xvzf make-3.80.tar.gz
cd make-3.80
./configure
./build.sh
# copy make to the directory with the binary and input and run the local make version
./make
# everything works as expected !!!
Is it the version 3.81 ?
wget http://ftp.gnu.org/gnu/make/make-3.81.tar.gz
tar xvzf make-3.81.tar.gz
cd make-3.81
./configure
./build.sh
# copy make to the directory with the binary and input and run the local make version
./make
# FAIL! Like with the make version in Debian.
Hence, I think I bumped into some very weird bug in GNU Make v.3.81.

PATH variable when calling make from XCode

For an iPad application I need to transform some CoffeeScript files into JavaScript files before bundling them with the application.
I tried to add a Makefile to my XCode project with the following code:
MANUAL_ROOT=IOS12BSH/manual
SCRIPTS_ROOT=$(MANUAL_ROOT)/scripts
COFFEE_SOURCES=$(SCRIPTS_ROOT)/*.coffee $(SCRIPTS_ROOT)/guides/*.coffee
JAVASCRIPT_TARGETS=$(COFFEE_SOURCES:.coffee=.js)
all: build
build: coffeescript
clean: clean_coffeescript
coffeescript: $(JAVASCRIPT_TARGETS)
clean_coffeescript:
rm -f $(JAVASCRIPT_TARGETS)
$(JAVASCRIPT_TARGETS): $(COFFEE_SOURCES)
coffee -c $(COFFEE_SOURCES)
Running this Makefile from the shell works without problems. However, after I added the Makefile as a target in XCode, I ran into problems.
The following error was produced by the Makefile:
coffee -c IOS12BSH/manual/scripts/*.coffee IOS12BSH/manual/scripts/guides/*.coffee
/bin/sh: coffee: command not found
make: *** [IOS12BSH/manual/scripts/*.js] Error 127
Command /Applications/Xcode.app/Contents/Developer/usr/bin/make failed with exit code 2
That is strange, as the coffee command is installed on my machine (it is installed under /opt/local/bin/coffee and /opt/local/bin is added to my $PATH in ~/.profile).
So I added an echo $(PATH) to my Makefile and it seems that the $PATH is different, when the Makefile is executed by XCode. XCode does not seem to read the settings from ~/.profile and therefore /opt/local/bin is not in $PATH.
What is the reason for this and how can I fix this, so that the coffee command is found?
Well, it seems that programs started via the Dock or Spotlight do not execute .profile and therefore $PATH is not set correctly.
So one way would be to set the $PATH in ~/.MacOSX/environments.plist. That works then apparently, but you will need a restart before it works.
Another way is to start XCode always from the command line with open projectfile.
This answer explains the problem in detail:
https://stackoverflow.com/a/14285335/751061
What ended up working best for me is just to launch Xcode from the command line.
I wrote a simple bash script that looks like:
source ~/.bash_profile # This is the trick that gets us our environment variables.
open -a "Xcode"
And then I call it from an Applescript Application just to give it a bundle I could put on the dock:
do shell script "~/xcode_launcher"
Sourcing your profile is necessary in the bash script, because running a script from Applescript doesn't ever source from a profile, so you still wouldn't have your default environment variables.
SAme thing with ant command. It works on terminal, not if Xcode have to do it. Only way to got it work: sudo open project.xcodeproj in terminal.

Resources