What is the practical purpose of -c in the linux install (/usr/bin/install) command? - installation

What is the practical purpose of -c in the linux install command? The man page shows:
-c (ignored)
I came across this scenario while installing Nagios command-mode:
/usr/bin/install -c -m 775 -o nagios -g nagios -d /usr/local/nagios/var/rw

From the install man page:
-c Copy the file. This is actually the default. The -c option is only included for backwards compatibility.
I think it exhibits the same behavior for copying files and creating directories. Also, taking a look at https://github.com/NagiosEnterprises/nagioscore/blob/master/Makefile.in#L37-L39 and https://github.com/NagiosEnterprises/nagioscore/blob/master/Makefile.in#L415-L421 we can see that these are set by the ./configure script.
Taking a look at configure.ac we see that it is the default autoconf macros that determine the binary to use: https://github.com/NagiosEnterprises/nagioscore/blob/master/configure.ac#L17-L19. And it is Nagios specific for setting the $(COMMAND_OPTS): https://github.com/NagiosEnterprises/nagioscore/blob/master/configure.ac#L237-L240.
Hope this helps!
TL;DR: It's a relic and doesn't matter :)

Historically, BSD's install would not copy files unless specified with the -c option. GNU Coreutils's version of install copied files by default, and provided -c as a BSD-compatibility option that is ignored. The GNU Coreutils manpage simply says
-c (ignored)
and doesn't provide context. This is the version of coreutils present on most Linux systems.
FreeBSD's manpage is a little bit more descriptive:
-c Copy the file. This is actually the default. The -c option is only included for backwards compatibility.
Nowadays, there's no particular reason to use the -c option unless you want compatibility with very old systems. That being said there's also no particular downside to leaving it in since it's unlikely you'll be hitting the character limit for the command line, so it's kind of an "up to you" sort of thing.

Related

What does gcc -E option stand for?

According to gcc manual, the -E option only preprocesses the .c source file, without running the compiler and just giving an input file (.i). But what does the -E stand for?
Summary
This option was introduced on compilers much earlier than GCC, and GCC used the same naming for compatibility.
My best guess from the historical evidence is that -E stands for "expand macros".
The authors of those earlier compilers couldn't call it -P because there was already a -P option, which also ran only the preprocessor, but wrote the output to .i files instead of to standard output. -p was also taken.
Over time, -E became preferred to -P, and when GCC was written, it supported only -E and not -P.
Despite being supposedly off topic for Stack Overflow, I think a bit of history will help explain how this option got its name.
gcc(1) inherited its basic command line options from much earlier Unix C compilers. Many versions can be found in the Unix Tree archive.
It looks like the first version that supported -E was Research Unix V7, circa 1979: cc(1) source, man page source. There was also a -P option that also just ran the preprocessor, but sent the result to a file foo.i instead of to standard output. V6 had already supported -P but not -E: cc(1) source, man page source.
This at least answers why -E wasn't named -P instead: because -P was already in use. (And -p was also taken, it was used to request profiling.) The only hint I found as to why -E was chosen is that the corresponding flag variable in the source code is named exflag. I would hazard a guess that this stands for "expand", as what -E does is basically to expand macros.
It appears that -P was eventually deprecated in favor of -E. V8 still supported it, but omitted it from the man page. V10 (circa 1989) included two versions of the compiler, cc which compiled traditional C, and lcc for ANSI C. The man page says that cc supports -P with the preprocessor behavior, but for lcc, -P did something else ("write declarations for all defined globals on standard error"). They both supported -E. On other fronts, 32V and BSD, at least initially, supported both, but -P would emit a warning that it was obsolete and -E should be used instead.
It looks like gcc, from its earliest version, only supported -E and not -P. Since then, a -P option has been introduced, but it does something else ("inhibit generation of linemarkers").

Why don't developers use the `install` command?

While looking at my friend's Makefile, I noticed that he used the install shell command. From what I can tell, the command allows you to install and chmod files with one fell swoop. The command came up in a subsequent conversation of ours, and he said he had heard that the command is considered somewhat archaic, and that developers should use cp, mv, chmod etc. for modern projects.
Strangely, this has been my only encounter with the command. This leads me to believe that the command has indeed been rejected and hence forgotten. Is this true? Is there some sort of security flaw with the program? From my possibly naive point of view, using a single command is always better than using many commands
I suspect the answer is that the install command is pretty much only used in scripts and makefiles (such as the automake makefiles that #Jack Kelly describes), and almost never interactively. Thus people rarely see it 'over someone's shoulder', and it doesn't lodge in their consciousness.
It is however, as you say, pretty much exactly the right tool for this job. The problem is that it's not a POSIX command, so it's wise not to use any terribly exotic options. The version of it used in automake makefiles is supplemented by a distributed shell script if the configure script hasn't convinced itself that the local version is sufficiently compatible.
See the autoconf manual's discussion of portable shell scripting, for some useful tips on this general topic.
Makefiles generated by automake still use it, as evidenced by the line (or similar):
checking for a BSD-compatible install... /usr/bin/install -c
in the output of configure.

Is there an easy way to COLOR-CODE the compiler outputs?

gcc (or other compilers) often generate huge text output and it's very difficult to see where the error is or miss warnings. I've done some search but havn't found a clean simple solution to color code the compiler output (so for instance warnings are yellow, errors are red, etc...)
Gcc 4.9 seems to have added this feature via the -fdiagnostics-color flag:
here's an alternative if you are looking for something very simple:
#!/bin/bash -e
make ${#} 2>&1 | perl -wln -M'Term::ANSIColor' -e '
m/Building|gcc|g++|\bCC\b|\bcc\b/ and print "\e[1;32m", "$_", "\e[0m"
or
m/Error/i and print "\e[1;91m", "$_", "\e[0m"
or
m/Warning/i and print "\e[1;93m", "$_", "\e[0m"
or
m/Linking|\.a\b/ and print "\e[1;36m", "$_", "\e[0m"
or
print; '
Just alias your make to this script and make sure it's executable...
Debian and Ubuntu gives the colorgcc package for that purpose.
And I usually run gcc (and make) thru emacs with M-x compile then the messages are colorized.
addenda
GCC 4.9 has a native colorization facility and GCC 6 - released end of April 2016 - (and probably GCC 5 too) is enabling it by default (when stdout is a terminal).
Ok, I'll just leave a notice about my own (python based) tool also :)
It is called Pluggable Output Processor and designed not only to colorize output of one particular program. Here is sample GCC output before:
After:
See colorgcc, a perl script that coulours the gcc output.
How to install and use colorgcc to colorize your gcc compiler output:
At least 3 answers here so far mention colorgcc, but NONE OF THEM EXPLAIN HOW TO INSTALL IT! (And it's not obvious). So, here's how to install the latest version in Ubuntu!
Go here and click "Clone or download" --> "Download Zip". I saved it into "~/Downloads/Install_Files"
Navigate to it in your file browser and right click it and go to "Extract Here." I now have a directory called "~/Downloads/Install_Files/colorgcc-master".
Copy the "colorgcc.pl" script to "/usr/bin/colorgcc" to "install" it (be sure to use the correct directory according to where you extracted it above): sudo cp ~/Downloads/Install_Files/colorgcc-master/colorgcc.pl /usr/bin/colorgcc
Make it executable: sudo chmod +x /usr/bin/colorgcc
Make the "~/bin" directory if it does not yet exist: mkdir ~/bin
*Make symbolic links that point to "/usr/bin/colorgcc" so that whenever you call gcc or g++ it automatically calls colorgcc instead:
ln -s /usr/bin/colorgcc ~/bin/g++
ln -s /usr/bin/colorgcc ~/bin/gcc
(if you ever want to uninstall colorgcc for some reason just delete these symbolic links "~/bin/g++" and "~/bin/gcc", and the Perl script: "/usr/bin/colorgcc" and you're done)
Done!
Here is a sample g++ output now when I call g++ -Wall -std=c++11 time_until_overflow_2.cpp -o time_until_overflow_2:
*Note: making these symbolic links in "~/bin" only works if "~/bin" is in your PATH variable in a location before the folder where the actual gcc and g++ executables are located. To ensure you have "~/bin" in your path you can view the PATH variable contents with: echo $PATH. If you don't see "/home/YOUR_USERNAME/bin" at the beginning of your path, add it with: export PATH=~/bin:$PATH.
References:
See here for more info. and for where I originally learned most of these steps: https://imranfanaswala.wordpress.com/2009/02/02/setting-up-colorgcc/. Thanks Imran Fanaswala!
~GS
you can use GilCC which is a Ruby tool that will convert GCC output to color in real-time. Right now you have two choices: Perl script (colorGCC) or GilCC and if you already work with Ruby you will like GilCC.
Unique to GilCC; GilCC has warning and errors counters and also shows compile time, very handy when you are trying to improve things. Because it is in Ruby it is cross platform. It is flexible and you can add more gems to customize it anyway you want.
The link to the download page is here.
https://github.com/gilmotta/GilCC
Although GCC 4.9 has -fdiagnostics-color option to enable colored outputs to terminals, I have created a tiny tool called 'crror' to get colorized compiler output.
It supports outputs from make as well. I can add colorize patterns for other tools if anyone requires.

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.

How to stop MinGW and MSYS from mangling path names given at the command line

On Windows, I'm cross-compiling a program for ARM/Linux using CodeSourcery's cross-compiler suite. I use MinGW MSYS as my command interpreter, and very often it will mangle my paths and pathnames. For example, to build my program, I invoke
arm-none-linux-gnueabi-gcc.exe -Wall -g \
-Wl,--dynamic-linker=/usr/lib/myrpath/ld-linux.so.3 \
-Wl,-rpath=/usr/lib/myrpath \
-I../targetsysroot/usr/include \
myprogram.c -o myprogram
Of course, I want /usr/lib/myrpath inserted verbatim into the myprogram executable - the ARM Linux target I'm compiling for doesn't use MinGW or MSYS. But here's what ends up going into it:
...
0x0000000f (RPATH) Library rpath: [C:/MinGW/msys/1.0/lib/myrpath]
...
Not exactly what I wanted. If I invoke GCC on the cmd.exe command line directly, I get the right rpath in the executable. If I invoke GCC on the MSYS command line, I get the mangled rpath. If I invoke GCC with a Makefile that is run with make from the cmd.exe command line, I still get a mangled rpath (!)
Any ideas how I might turn off this annoying behavior?
There is a way to suppress the path translation by setting MSYS_NO_PATHCONV=1 in Windows Git MSys or MSYS2_ARG_CONV_EXCL="*" in MSYS2.
Alternatively, you can set the variable only temporarily just for that command by putting the assignment just before the command itself:
MSYS_NO_PATHCONV=1 arm-none-linux-gnueabi-gcc.exe -Wall -g \
-Wl,--dynamic-linker=/usr/lib/myrpath/ld-linux.so.3 \
-Wl,-rpath=/usr/lib/myrpath \
-I../targetsysroot/usr/include \
myprogram.c -o myprogram
I just discovered a neat trick to avoid MSYS/MinGW translating the paths for you.
If you use double-slash to start the path, then MSYS won't translate the path to DOS format. So in OP's example, the -rpath switch should be specified like this:
-Wl,-rpath=//usr/lib/myrpath
All Unix/Linux tools seem to handle such spurious slashes without any problem, so even though your binary's rpath will start with //usr/... I think the loader will do the right thing.
I don't think there's a way to switch this off. MSYS is a fork of an old Cygwin version with a number of tweaks aimed at improved Windows integration, whereby the automatic POSIX path translation when invoking native Windows programs is arguably the most significant. The trouble with that is that it isn't always possible to tell whether an argument is a path or something else, or whether, as in this case, it is in fact a path that nevertheless shouldn't be translated. The translation is guided by a set of heuristics.
You could try using MinGW make instead of MSYS make (yes, they're different things), which is a native Windows build of make without POSIX path support and conversion. Install with mingw-get install mingw32-make and invoke as mingw32-make.
Or you could try Cygwin, ideally with a Cygwin build of the toolchain.
Indeed, in the original MSYS project provided by MinGW.org, there is no way to disable the Posix path conversion.
That's why I made a little fork of the msys-core runtime which supports the MSYS_NO_PATHCONV flag introduced with the Git for Windows fork. In that way, you may use MSYS_NO_PATHCONV environment variable as in the Git for Windows but in the original MinGW/MSYS.
So in summary, to disable this Posix path convesion:
For MSYS2 (built-in): MSYS2_ARG_CONV_EXCL="*"
For Git for Windows (built-in): MSYS_NO_PATHCONV=1
For MinGW.org (with msys-core-extended): MSYS_NO_PATHCONV=1.
export MSYS_NO_PATHCONV=1 was necessary in my case on git-bash on windows (as noted by dx_over_dt above. )
Unfortunately putting two forward slashes for this example doesn't work as expected.
rsync -rvztn --delete --exclude="/application/logs/" ...
I want 'rsync' to exclude files only at /application/logs which is at the top level, hence the leading forward slash. Adding two forward slashes will not cause it to exclude this directory. I have to resort to the less accurate --exclude="application/logs/".

Resources