How do I work around gnu linker command line pickiness? - gcc

This question and its answer explains the importance of linking command line order.
However, I deal with a lot of makefiles containing lines like
$(CC) $(LDFLAGS) $^ -o $#
Aparently, commands like these just work on some systems, but not on mine. Is there a way to work around this behaviour other than finding and patching all Makefiles like these?
I am using gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
EDIT for clarification:
I do a lot of patching and integration as part of my job(Usually buildroot or LTIB) , and I come across multiple makefiles written like this. Also some example compiling commands on the web follow the same pattern.

So, the problem is that some idiot has created a makefile that puts all the library options before the .o file. Presumably there is some broken toolchain out there that doesn't care, but that doesn't help you.
There's only two options here:
Fix the makefile.
Create a compiler wrapper that reorders the options. Such a wrapper would be broken in general, but could make it work for the exact pattern used by your makefiles.
I did wonder if --start-group would help you here, but a quick experiment suggests not.

Related

Disable optimizations for a specific file with autotools

I'm working on setting up autotools for a large code base that was once just a bash script compile and later just hand written Makefiles.
We have a set of files that require that compiler optimizations be turned off. These files are already in their own subdirectory, so they will have their own Makefile.am.
What's the proper way to drop any existing compiler optimizations and force a -O0 flag on the compiler for these specific files?
I went with Brett Hale's comment to use subpackages. I was able to insert
: ${CFLAGS="-O0"}
before AC_PROG_CC, which sets the appropriate optimization. The other solutions do not work, since the -g -O2 was getting added very last. You can never get another -O variable after it.
You don't have to remove existing optimizations: the last value of -O on the compiler invocation will be used, so it's good enough to just add -O0 at the end.
This is not directly supported by automake, but there's a trick you can use defined in the documentation.
Otherwise if you know you'll only ever invoke your makefile with GNU make you can play other tricks that are GNU make specific; you may have to disable automake warnings about non-portable content.

Change older makefile system to take advantage of parallel compiles

We use Microsoft NMAKE to compile a large number of native C++ and some Intel Fortran files. Typically the makefiles contains lines such as this (for each file):
$(LINKPATH)\olemisc.obj : ole2\olemisc.cpp $(OLEMISC_DEP)
$(CCDEBUG) ole2\olemisc.cpp
$(GDEPS) ole2\olemisc.cpp
OLEMISC_DEP =\
e:\ole2\ifaceole.hpp\
e:\ole2\cpptypes.hpp\
etc.
It works fine, but compiles one file at a time. We would like to take advantage of multi core processors and compile more than one file at a time. I would appreciate some advice about the best way to make that happen, please. Here is what I have so far.
One: GNU make lets you execute parallel jobs using the --jobs=2 option for example and that works fine with GCC (we cant use GCC sadly). But Microsoft's NMAKE does not seem to support such an option. How compatible would the two name programs be, and if we did start using GNU MAKE, can you run two cl.exe processes at the same time? I would expect them to complain about the PDB (debug) file being locked, or does one of the newer cl.exe command line arguments get you around that?
Two: cl.exe has a /MP (build with multiple processes) flag, which lets you compile multiple files at the same time if passed together via the command line, for example:
cl /MP7 a.cpp b.cpp c.cpp d.cpp e.cpp
But using this would require changes to the makefile. Our make files are generated by a our own program from other files, so I can easily change what we put in the makefiles. But how do you combine the dependencies from different cpp files together in the makefile so they get compiled together via one cl.exe call? Each .obj is a different target with a set of commands to make it?
Or do I change the makefile to not call cl.exe, but rather some other little executable that we write, which then collects a series of .cpp files together and shells out to cl.exe passing multiple arguments? That would work and seems doable, but also seems overly complicated and I cant see anyone else doing that.
Am I missing something obvious? There must be a simpler way of accomplishing this?
We do not use Visual Studio or a solution file to do the compiles, because the list of files is extensive, we have a few special items in our makefiles, and theoretically do not want to be overly tied to MS C++ etc.
I thoroughly recommend GNU make on windows. I tend to use cygwin make as the environment it creates tends to be very portable to Unix-like platforms (Mac and Linux for a start). Compiling using the Microsoft toolchain, in parallel and with 100% accurate dependencies and CPU usage works very well. You have other requirements though.
As far as your nmake question goes, look up batch-mode inference rules in the manual. Basically, nmake is able to call the C compiler once, passing it a whole load of C files in one go. Thus you can use the compiler's /MP... type switches.
Parallel compiling built into the compiler? Pah! Horribly broken I say. Here is a skeleton anyway:
OBJECTS = a.obj b.obj c.obj
f.exe: $(OBJECTS)
link $** -o $#
$(OBJECTS): $$(#R).c
# "The only syntactical difference from the standard inference rule
# is that the batch-mode inference rule is terminated with a double colon (::)."
.c.obj::
cl -c /MP4 $<
EDIT
If each .obj has its own dependencies (likely!), then you simply add these as separate dependency lines (i.e., they don't have any shell commands attached).
a.obj: b.h c.h ../include/e.hpp
b.obj: b.h ../include/e.hpp
∶
Often such boiler plate is generated by another tool and !INCLUDEd into the main makefile. If you are clever, then you can generate these dependencies for free as you compile. (If you go this far, then nmake starts to creak at the seams and you should maybe change to GNU make.)
One further consideration to keep in mind here is this: You basically have to define one batch rule for each path and extension. But if you have two files with the same name in two different source directories with a batch inference rule for both of those directories, the batch rule might not pick the one you want.
Basically the make system knows it needs to make a certain obj file, and as soon as it finds an inference rule that lets it do that, it will use it.
The work around is to not have duplicate named files, and if that cant be avoided, dont use inference or batch rules for those files.
Ok, I spent some time this morning working on this, and thanks to bobbogo, I got it to work. Here are the exact details for anyone else who is considering this:
Old style makefile which compiles one file at a time has tons of this:
$(LINKPATH)\PS_zlib.obj : zlib\PS_zlib.cpp $(PS_ZLIB_DEP)
$(CC) zlib\PS_zlib.cpp
$(LINKPATH)\ioapi.obj : zlib\minizip\ioapi.c $(IOAPI_DEP)
$(CC) zlib\minizip\ioapi.c
$(LINKPATH)\iowin32.obj : zlib\minizip\iowin32.c $(IOWIN32_DEP)
$(CC) zlib\minizip\iowin32.c
Note that each file is compiled one at a time. So now you want to use the fancy Visual Studio 2010 /MP switch "/MP[n] use up to 'n' processes for compilation" to compile multiple files at the same time. How? Your makefile needs to make use of batch inference rules in nmake, as follows:
$(LINKPATH)\PS_zlib.obj : zlib\PS_zlib.cpp $(PS_ZLIB_DEP)
$(LINKPATH)\ioapi.obj : zlib\minizip\ioapi.c $(IOAPI_DEP)
$(LINKPATH)\iowin32.obj : zlib\minizip\iowin32.c $(IOWIN32_DEP)
#Batch inference rule for extension "cpp" and path "zlib":
{zlib}.cpp{$(LINKPATH)}.obj::
$(CC) $(CCMP) $<
#Batch inference rule for extension "c" and path "zlib\minizip":
{zlib\minizip}.c{$(LINKPATH)}.obj::
$(CC) $(CCMP) $<
In this case, elsewhere, we have
CCMP = /MP4
Note that nmake inference batch rules do not support wildcards or spaces in the paths. I found some decent nmake documentation somewhere that states that you need to create a separate rule for every extension and source file location, you can not have one rule if the files are in the different locations. Also, files that use #import can not be compiled with /MP.
We have a tool that generates our makefiles, so it now also also generates the batch inference rules.
But it works! The time to compile one large dll went from 12 minutes down to 7 minutes! Woohoo!

BSD Make and GNU Make compatible makefile

I have a BSDmakefile and GNUmakefile that are pretty much identical except for dependency management.
The GNUmakefile:
ifneq ($(MAKECMDGOALS), "clean")
-include $(dependencies)
endif
The BSDmakefile:
.for i in $(dependencies)
.sinclude "${i}"
.endfor
Is there a way to make it so that I can detect if I am running under gmake or bsdmake and then execute the appropriate include statements based off of that? I remember seeing someone take advantage of a quirk in both makefile processors so that they could achieve a similar effect.
Alternatively, if there is a better approach than this, I would like to know! (switching to SCons or CMake is not appropriate!)
Thanks!
You could put your GNU-specific stuff in GNUmakefile, your BSD-specific stuff in BSDmakefile, and your common stuff in a file named Makefile.common or similar. Then include Makefile.common at the very beginning of each of the other two. Downside is, now you have 3 makefiles instead of 2. Upside, you'll only be editing 1.

using openmp with a makefile and g++

I am building a large project with a makefile that was originally built with icpc, and now I need to get it running with g++.
When it compiles the file that uses openmp, it uses the -c flag, and doesn't use any libraries, so it ends up being serial instead of openmp. All of the examples I am seeing aren't using this -c flag.
Is there some way to compile without linking, but using openmp?
edit:
I've been using the -lgomp flag(and the library is on the library path):
g++ -lgomp -c -w -O4 mainS.cpp
g++: -lgomp: linker input file unused because linking not done
Edit: my boss made several mistakes in the code, the makefile, and the documentation. Sorry to have wasted your time, at least it was less than the 5 hours I spend on it =/
Are you passing the flag to enable OpenMP (IIRC it's something like -fopenmp? If you don't chances are the compiler will ignore the OpenMP-related primitives and just produce serial code.
I don't think that -c (ie, compile only, don't like) has anything to do with your problem.
Perhaps the documentation helps...

Separating objects and source with a makefile

I have been having troubles getting my makefiles to work the way I want. First off, I would like to say this is POSIX make, as in http://www.opengroup.org/onlinepubs/009695399/utilities/make.html I am needing my build system to work with both BSDs and GNUs(Linux).
What I am wanting is a zero maintenance makefile. I want it to just compile all .c and .asm files in src/ and place the object files in objs/ and then to link everything in objs/ to a binary file.
I can do a lot, but I can't get it to separate the source and obj files.
I am ok if this requires a little built-in shell scripting (using POSIX defined /bin/sh), but I can just not get the dependencies to work right. I want it to only build the object file if the source file is newer.
My closest is this:
${C_OBJS}: ${HDRS} ${*:objs/%=src/%}.c
${CC} ${CFLAGS} -c ${*:objs/%=src/%}.c -o $*.o
This has the problem that I must still specify C_OBJS=objs/foo.o and such and also it is just barely not POSIX and therefore, compiles with BSD make but not GNU make.
The POSIX version of make does not explicitly support file names with slashes in them, nor does it make provision for separating source files in a different directory from the object files. And, as noted by #caskey, it does not support any notation using '%' characters, though it notes that such rules exist and recommends that they be reserved for use as metacharacters.
Consequently, you probably cannot do what you want with standard POSIX make.
In practice, you can often do what you seek with specific implementations of make, but the resulting makefile has limited portability.
Consider using a makefile generation systems of some sort - cmake or the auto-tools (autoconf, libtool, automake, etc). Or one of the many reworkings of the basic concepts of make:
scons
ant
cake
cook
bras
...and a dozen I've forgotten or not heard of...
POSIX make doesn't support constructs like?
objs/%.o : src/%.c
${CC} ${CFLAGS} -c $< -o $#
Forgot the question mark at the end, hope that makes my comment more clear.

Resources