What does -A option do in gcc? - linux

What does the -A option in gcc do? I am using arm-none-linux-gnueabi-gcc.
Below is the rule in my makefile.
$(SH_OBJ): $(OBJS)
$(CC) $(LFLAGS) -o $#-debug -A $#-debug $^ $(LIBPATH) $(LDLIBS)

I suggested looking it up, and since it's an option I've never seen before, I followed my own advice. -A is an option passed to the preprocessor:
From documentation:
-A predicate=answer
Make an assertion with the predicate predicate and answer answer. This form is preferred to the older form -A predicate(answer), which is still supported, because it does not use shell special characters. See Obsolete Features.
-A -predicate=answer
Cancel an assertion with the predicate predicate and answer answer.
(The argument in your makefile is $#-debug, though, which lacks the = to split the predicate and answer parts. Odd.)
And documentation on assertions:
Assertions are a deprecated alternative to macros in writing conditionals to test what sort of computer or system the compiled program will run on. Assertions are usually predefined, but you can define them with preprocessing directives or command-line options.
Assertions were intended to provide a more systematic way to describe the compiler’s target system and we added them for compatibility with existing compilers. In practice they are just as unpredictable as the system-specific predefined macros. In addition, they are not part of any standard, and only a few compilers support them. Therefore, the use of assertions is less portable than the use of system-specific predefined macros. We recommend you do not use them at all.
I'm guessing this is a makefile for a really old project?

Related

make multithreaded build with one recipe?

If I have something like the following
%.o: %.c
gcc -c -o $# $<
and I run make with -j, will make do a multithreaded build? I've read the documentation for -j, and it says it will run multiple recipes in parallel. In my example, there seems to only be one recipe, but I'm not sure if make will do a multithreaded build anyways.
It's one rule, but it's a pattern rule. A pattern rule provides a "template" for make to know how to update any .o file based on its counterpart .c file.
So if you want to build 10 object files from 10 source files, make will apply this pattern rule to each one to build it. If you use -j10, then make will invoke all the recipes in parallel since they don't depend on each other.
Yes, this is run with the number of jobs you pass to the -j parameter (e.g. number of processors on your machine plus one seems to be a good value). This rule will most likely consume most of the build time in larger projects, you should be able to see a considerable speed-up when compared to a -j1 run.

Clarify makefile syntax

Could someone clarify how this code works?
PRE_PROC_EXE := $(shell which pre_proc.pl)
PRE_PROC2_EXE := $(shell which pre_proc2.pl)
$(filter $(TMP_DIR)/%.c,$(FILES)):$(TMP_DIR)/%.c: $(SRC_DIR)/%.c
$(PRE_PROC_EXE) < $< > $#
I was trying to add one more step of pre processing on the files generated by step one (using PRE_PROC2_EXE). How do I do that?
$(shell) is a make function which runs a shell command and returns its output.
So PRE_PROC_EXE contains the output from running which pre_proc.pl and PRE_PROC2_EXE contains the output from running which pre_proc2.pl. (I'll point out that which isn't portable, isn't guaranteed to exist and doesn't have a specification for its behavior so you can't rely on its output so using it like this isn't a great idea.)
The rest is a Static Pattern Rule which operates on the entries in $(FILES) that match the $(TMP_DIR)/%.c pattern (from $(filter $(TMP_DIR)/%.c,$(FILES))) and applies the recipe to them using the matching $(SRC_DIR)/%.c file as the prerequisite ($<) and the matching $(TMP_DIR)/%.c file as the target ($#).
As to how to apply PRE_PROC2_EXE to this that isn't easily answerable as you haven't explained how that script works or how you need to apply it.
How does that work? It works by magic! – in my opinion, that's an awful bit of Makefile (practical remarks at the end).
make is a simple system, with simple syntax, which does one thing well. Over the years, however, it has acquired (and yes, I'm looking at you, GNU Make) a crust of elaborate functions, with compressed syntax, and a vast manual, which together make some Makefiles look like line-noise. Such as here.
Sometimes you have to do more-or-less clever things to build a bit of software, but (in my opinion and experience) these are much more naturally and comprehensibly handled by adding sophistication to the rules, not the Makefile syntax itself. That way, you leave the structure of the Makefile reasonably intelligible, which is important if you need to understand and adjust how the software is built.
I write quite complicated Makefiles, but only occasionally use a filter as complicated as patsubst (but I do generally use GNU Make – BSD/POSIX Make is an asceticism too far).
Also, you could use auxiliary tools to do certain parts of the heavy lifting. For example, you might use autoconf to do the tool-searching, write
PRE_PROC_EXE=#PRE_PROC_EXE#
PRE_PROC_EXE2=#PRE_PROC_EXE2#
in a Makefile.in, and write a configure.ac which includes
dnl Process this file with autoconf
AC_INIT(fooprog, 0.1-SNAPSHOT, author#example.org)
AC_PATH_PROG(PRE_PROC_EXE, pre_proc.pl, NOT_FOUND)
AC_PATH_PROG(PRE_PROC_EXE2, pre_proc2.pl, NOT_FOUND)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
Then autoconf; ./configure would find pre_proc{,2}.pl and substitute them into a new Makefile. autoconf takes a little getting used to, first time, but is pretty natural once you get used to it.
Returning to your particular example, I have little idea what that target does (two colons? I don't want to know...), but you might be able to adjust the rule to
$(PRE_PROC_EXE) < $< | $(PRE_PROC_EXE2) > $#
to pass the input *.c files through both preprocessors.

How to get same Pre-processor output for aCC (Hp-Ux) and g++ (Linux)?

I've scripts specifically written to perform certain actions on HpUx pre-processor output and get desired details.
HpUx-ia64.
Linux-x86_64.
Now I need to migrate the same to Linux. Instead of rewriting tool entirely for Linux, how can I get the g++ -E (linux) output same as that of hpux aCC -E on a sourcename.
Instead of rewriting tool entirely for Linux, how can I get the g++ -E (linux) output same as that of hpux aCC -E on a sourcename.
Short answer: no.
Longer answer: compilers generally don't care what the output of $compiler -E looks like, so long as it fairly accurately represents the program. Some compilers can't even compile the output of $compiler -E foo.cc when $compiler -c foo.cc works just fine (this is a bug, but a low priority one).
Any tool or script that works on the preprocessed file (that's your script) should accept valid preprocessed result. Insisting that all compilers produce exactly the same preprocessed output is pointless; it's just not going to happen.
Even longer answer: g++ is open source. If you believe that it's easier to fix g++ to match output of aCC than it is to fix your script to accept either input, you have the power to do so (but I predict that it's at least 1000 times harder to do the former than the latter).
Finally, you did not provide any details of what differences you are trying to eliminate. Had you done so, this (or some other) answer might have been more useful.

Is there a way to get the -j parameter from a make invocation?

Lets say I call:
make -j 5
Is there a way, within my Makefile to get the -j parameter ?
My goal is to call scons from a Makefile a to keep the ability to use several jobs to fasten compilation.
Something like:
# The Makefile
all:
scons -j ${GET_J_PARAMETER}
Thank you.
Foot note: I know I should better call scons directly but some of the developers where I work have been typing make for almost ten years and it seems impossible for them to type anything else to build their libraries...
I think the MAKEFLAGS contains that information.
Read more about it here GNU Make
Section 7.3 explains how to test for a specific parameter.

Automake and files with the same name

I've a C++ autoconf managed project that I'm adapting to compile on FreeBSD hosts.
The original system was Linux so I made one AM_CONDITIONAL to distinguish the host I'm building and separate the code into system specific files.
configure.ac
AC_CANONICAL_HOST
AM_CONDITIONAL([IS_FREEBSD],false)
case $host in
*free*)
AC_DEFINE([IS_FREEBSD],[1],[FreeBSD Host])
AM_CONDITIONAL([IS_FREEBSD],true)
BP_ADD_LDFLAG([-L/usr/local/lib])
;;
esac
Makefile.am
lib_LTLIBRARIES=mylib.la
mylib_la_SOURCES=a.cpp \
b.cpp
if IS_FREEBSD
mylib_la_SOURCES+=freebsd/c.cpp
else
mylib_la_SOURCES+=linux/c.cpp
endif
When I run automake it fails with this kind of message:
Makefile.am: object `c.lo' created by `linux/c.cpp' and `freebsd/c.cpp'
Any ideas on how to configure automake to respect this conditional even in the Makefile.in build proccess?
I this works if the files have diferent names, but it's c++ code and I'm trying to keep the filenames the same as the class name.
Thanks in advance!
You could request for the objects to be built in their respective subdirectories with
AUTOMAKE_OPTIONS = subdir-objects
Another option, besides subdir-objects, is to give each sub-project some custom per-project build flags. When you do this, automake changes its *.o naming rules to prepend the target name onto the module name. For example, this:
mylib_la_CXXFLAGS=$(AM_CXXFLAGS)
mylib_la_SOURCES=a.cpp b.cpp
will result in the output files mylib_la-a.o and mylib_la-b.o, rather than a.o and b.o. Thus you can have two different projects with the same output directory that each have, say, a b.cpp file, and not have their outputs conflict.
Notice that I did this by setting the project-specific CXXFLAGS to the values automake was already going to use, AM_CXXFLAGS. Automake isn't smart enough to detect this trick and use the shorter *.o names. If it happens that you do need per-project build options, you can of course do that instead of this hack.
There's a whole list of automake variables that, when set on a per-executable basis, give this same effect. So for instance, maybe one sub-project needs special link flags already, so you give it something like:
mylib_la_LDFLAGS=-lfoo
This will give you the prefixed *.o files just as the AM_CXXFLAGS trick did, only now you are "legitimately" using this feature, instead of tricking automake into doing it.
By the way, it's bad autoconf style to change how your program builds based solely on the OS it's being built for. Good autoconf style is to check only for specific platform features, not whole platforms, because platforms change. FreeBSD might be a certain way today, but maybe in the next release it will copy a feature from Linux that would erase the need for you to build your program two different ways. Or, maybe the feature you're using today is deprecated, and will be dropped in the next version.
There's forty years of portable Unix programming wisdom in the autotools, grasshopper. The "maybes" I've given above have happened in the past, and will certainly do so again. Testing individual features is the nimblest way to cope with constantly changing platforms.
You can get unexpected bonuses from this approach, too. For instance, maybe your program needs two nonportable features to do its work. Say that on FreeBSD, these are the A and B features, and on Linux, they're the X and Y features; A and X are similar mechanisms but with different interfaces, and the same for B and Y. It could be that feature A comes from the original BSDs, and is in Solaris because it has BSD roots from SunOS in the 80's, and Solaris also has feature Y from it's System V based redesign in the early 90's. By testing for these features, your program could run on Solaris, too, because it has the features your program needs, just not in the same combination as on FreeBSD and Linux.

Resources