ccache does not support some compiler options (e.g. --coverage). If there is an unsupported compiler options it compiles but the cache is not used.
There are more than one ways how to enable ccache (modifying PATH, using CC/CXX environment variables).
I would like to detect if the compiler uses ccache and if yes disable the unsupported compiler options.
The best i have come up with is something like this:
CC = $(shell which $(CC))
ifeq (,$(findstring ccache,$(CC)))
Any ideas how to improve this?
This might be a more elegant solution:
ifeq ($(shell readlink -f `which $(CC)`),$(shell which ccache))
echo "Using ccache"
else
echo "Not using ccache"
endif
Smani's solution may not work, depending on how ccache in configured (e.g. in RedHat Linux's ccache 3.3.4, t the compiler symlinks in /usr/lib64/ccache/ point to /usr/bin/ccache but which ccache returns /bin/ccache).
This solution doesn't care where ccache is located and even works if ccache is used as a prefix:
ifeq ($(shell $(CC) -xc -c - --ccache-skip </dev/null 2>&1),)
echo "Using ccache"
else
echo "Not using ccache"
endif
This works by compiling an empty file and checking whether the compiler knows about the ccache --ccache-skip flag.
Note that once you know ccache is enabled, instead of omitting the --coverage flag, you could preface it with --ccache-skip.
Note also that even if ccache is in the path, it may be disabled by the CCACHE_DISABLE environment variable or by the ccache.conf file.
Related
I have a project that basically compiles from the command line in the following form:
g++ -o stack_raster stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
I made a Makefile, and this is the content:
CXX =g++
LDDFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
However I got a collect2: error: ld returned 1 exit status.
A second variation of my Makefile I tried was:
CXX = g++
CPPFLAGS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rem -f stack_raster
but I still receive the following message (even though the compile flags appear as they should for my program to compile successfully).
collect2: error: ld returned 1 exit status
<builtin>: recipe for target `stack_raster` failed
make: *** [stack_raster] Error 1
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
Does anyone could help me with a reference or hint about my problem, and how could I tackle it?
To begin with, you should have a look at the actual link command that make executed. It should have been echoed to make's output just before the error message from collect2. Understanding what's wrong with the command is the first step in determining how to fix your makefile.
In the first case, the command is probably something like
g++ stack_raster.cpp -o stack_raster
In the second, it is probably something like
g++ -lgdal -lboost_system -lboost_filesystem stack_raster.cpp -o stack_raster
The latter is probably also very similar to what you would get with the first makefile if you corrected the spelling of LDDFLAGS to LDFLAGS.
You will note that the library flags come in a different place in that command than they do in your manual command, and I assume you know that the order of objects and library flags on the linker command line is significant to Unix-style linkers such as GNU's (which is the one that the g++ driver will use).
You can certainly fix this by writing an explicit rule, as you describe in your own answer, but your makes' built-in rules may be up to the task, too. If you are using GNU make then they certainly are. For this purpose it is useful to know what the built-in rules actually are, and essential to know what the variables on which these rules depend mean.
Specifically,
LDFLAGS provides options to pass when invoking the linker, and conventionally, they appear on the command line before the objects being linked. As a result, this variable typically is not appropriate for specifying libraries (but it is fine for other link-specific options, such as -L to add directories to the library search path).
CPPFLAGS provides options for modulating the behavior of the C preprocessor (including when compiling C++). These do not typically appear at all in link(-only) commands executed by make, but they will appear (early) in commands for compiling object files from C or C++ sources, and in rules for building executables directly from C or C++ sources.
Neither of those is what you want, but if you are using GNU make, then its documentation for the former explicitly tells you what (with that make implementation) you should do instead:
Extra flags to give to compilers when they are supposed to invoke the
linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the
LDLIBS variable instead.
(emphasis added)
In GNU make, and perhaps some others, the LDLIBS variable serves exactly the purpose you need: to specify the libraries to link. These will appear at the end of the link command line from built-in rules, as you can confirm from GNU make's catalog of implicit rules, or from the list obtainable by running make -p in a directory containing no makefile.
So, with GNU make you can get the build you seem to want from the built-in rules, with this:
CXX = g++
LDLIBS = -lgdal -lboost_system -lboost_filesystem
all: clean stack_raster
clean:
rm -f stack_raster
In closing, I note that cleaning before building by default, as your examples do and mine imitates, largely defeats the purpose of using make instead of a simple script. Part of the point of make is to do the minimum work necessary, and if your target executable is present and not out of date with respect to its sources then there is no reason to force it to be rebuilt.
Check out the answer:
Set up my makefile to compile C with just "make"
YOu have to specify in the Makefile the file you want to create in this case stack_raster.exe and the objective file in this case stack_raster.cpp and specify the command line arguments you normally pass for compiling. So the Makefile would be something like:
CXX=g++
stack_raster.exe: stack_raster.cpp
g++ -o stack_raster.exe stack_raster.cpp -lgdal -lboost_filesystem -lboost_system
all: clean stack_raster.exe
clean:
rm -f stack_raster.exe
I have some -f compiler options in CFLAGS like -fsanitize=address and someone suggested to me a while ago that I also put those options in LDFLAGS so I did. It hasn't caused any problems.
My question is how can I tell what compiler options from CFLAGS also should go in LDFLAGS? Is it just the -f prefixed options? Thanks
I have some -f compiler options in CFLAGS like -fsanitize=address and
someone suggested to me a while ago that I also put those options in LDFLAGS
so I did. It hasn't caused any problems.
Not only it won't cause any problems but that's the only correct way to build sanitized program.
My question is how can I tell what compiler options from CFLAGS
also should go in LDFLAGS? Is it just the -f prefixed options?
It won't hurt if you simply do
LDFLAGS = $(CFLAGS) $(LIBS)
Compiler driver (/usr/bin/gcc) knows which high-level options are for the linker so unnecessary options will be simply filtered out. In case you wonder how this happens, run gcc with -dumpspecs flag:
$ gcc -dumpspecs
...
*link_command:
%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S: %(linker) %{!fno-use-linker-plugin:%{!fno-lto: -plugin %(linker_plugin_file) -plugin-opt=%(lto_wrapper) -plugin-opt=-fresolution=%u.res %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} }}%{flto|flto=*:%<fcompare-debug*} %{flto} %{fno-lto} %{flto=*} %l %{no-pie:} %{pie:-pie} ...
This looks a bit ugly but in reality that's just a mini-language for flag translation. Syntax details are given here (although I seriously doubt that you need need to know about them).
There is a project (Antlr3 for C) that can be built with ./configure && make && make install.
One of the flags that are used in the compilation command is -Wl,-soname -Wl,libantlr3c.so. The whole command is:
libtool: link: gcc -shared .libs/antlr3baserecognizer.o .libs/antlr3basetree.o \
.libs/antlr3basetreeadaptor.o .libs/antlr3bitset.o .libs/antlr3collections.o \
.libs/antlr3commontoken.o .libs/antlr3commontree.o .libs/antlr3commontreeadaptor.o \
.libs/antlr3commontreenodestream.o .libs/antlr3convertutf.o .libs/antlr3cyclicdfa.o \
.libs/antlr3debughandlers.o .libs/antlr3encodings.o .libs/antlr3exception.o \
.libs/antlr3filestream.o .libs/antlr3inputstream.o .libs/antlr3intstream.o \
.libs/antlr3lexer.o .libs/antlr3parser.o .libs/antlr3rewritestreams.o \
.libs/antlr3string.o .libs/antlr3tokenstream.o .libs/antlr3treeparser.o \
-m64 -Wl,-soname -Wl,libantlr3c.so -o .libs/libantlr3c.so
How can I remove only the -Wl,-soname -Wl,libantlr3c.so part?
I understand that the compiler and linker flags can be overridden with CFLAGS and LDFLAGS in the configure command. According to this link, it's something like
./configure CFLAGS=blah LDFLAGS=blah
Although I understand that they can/should be used as environment variables, something like
CFLAGS=BLAH LDFLAGS=blah ./configure
However, I think that those uses would try to override all the CFLAGS or LDFLAGS. I only want to exclude the -soname flag (which, I understand, -Wl, means that the compiler passes a flag to the linker.
None of my attempts with things like LDFLAGS=-soname= or CFLAGS="-Wl,soname -Wl,", and variations of them, were successful so far.
From this question it looks as if it was possible to remove flags from within a Makefile, but I can't see that being applicable to overriding flags from the command line with the configure command. It's also possible to provide these variables to the make command instead of the configure command, but that wasn't successful either.
Note, it wouldn't make sense for me to change the Makefile, since it's generated out of the configure command.
You cannot remove -soname because it's part of the way you build a shared library with GCC, and comes straight from libtool. Since you can't really build a shared object for ELF without a soname (well, you can, but it's not really useful) libtool won't let you remove that.
You probably are better off declaring what you try to achieve, because I have a feeling it has nothing really to do with -soname in that case.
I wrote a Makefile and I can't get it to work. I have an option which is supposed to select which processor to compile to. However, when I run make from the commandline it says:
tandex#tandex-P-6860FX:~/emulators/nintendo sdks/3DS SDK [HomeBrew]$ make
gcc -march=arm7tdmi -static -fexceptions -fnon-call-exceptions -fstack-check test.c -c
test.c:1:0: error: bad value (arm7tdmi) for -march= switch
make: *** [ALL] Error 1
But in the man pages for gcc, it states that arm7tdmi is a permissible value. Am I missing something?
Makefile:
#3DS Compilation Makefile (c) TanDex (TEQ)RunawayFreelancers
#
#Version 0.99 (Alpha) For *nix Devices
#
#Please Check Back Soon for 3rd SDK
#SELECT THE COMPILER TO USE! GCC RECOMMENDED!
#FOR SANITY SAKE, USE C FILES WITH GCC AND CPP FILES WITH G++
CC=gcc
#CC=g++
#OBJECTCOPY REFERENCE, DO NOT REMOVE
OBJC=objcopy
OBJREFS= -O Binary
#SELECT THE PROCESSOR TO TUNE IT TO. ARMV7 (Nintendo DS) or ARMV9(Nintendo DS
(Graphical Support))
#or ARM11 Core ARM1176JZ-S and ARM1176JZF-S (3DS Processor? Not Sure if Correct. Try
and see if they Work?)
#
#NOTE: DS GAMES REQUIRE BOTH A ARM7 AND ARM9 BINARY. RUN THIS TWICE (ONCE FOR EACH)
#
#UNCOMMENT FOR PROCESOR
PROCESSOR=arm7tdmi
#PROCESSOR=arm946e-s
#PROCESSOR=arm1176jz-s
#PROCESSOR=arm1176jzf-s
#FILES
#
#PLACE ALL OF THE FILES HERE, THAT ARE BEING COMPILED!
FILES=test.c
#SET BIN FILE NAME BASED ON PROCESSOR SELECTED
ifeq($(PROCESSOR),arm7tdmi)\
NAME=ARM7.BIN
ifeq($(PROCESSOR), arm946e-s)\
NAME=ARM9.BIN
ifeq($(PROCESSOR), arm1176jz-s)\
NAME=ARM11.BIN
ifeq($(PROCESSOR), arm1176jzf-s)\
NAME=ARM11.BIN
#CREATE OBJECTS
ifeq($(CC), gcc)\
OBJECTS=$(FILES:.c=.o)
ifeq($(CC), g++)\
OBJECTS=$(FILES:.cpp=.o)
#FLAGS! DO NOT CHANGE THESE!!!!!!!!!!! THAT MEANS YOU!!!!!
#
#FOR THOSE WHO WANT TO KNOW WHAT THESE DO, HERE THEY ARE:
#-mtune=$(PROCESSOR) FORE THE COMPILER TO TUNE OUTPUT TO THE SPECIFIED
PROCESSOR
#-static REQUIRED FOR CLEAN BINARY OUTPUT?? (NOT SURE WHAT THIS
DOES, BUT WAS SUGESTED ON A POST ON STACKOVERFLOW)
#-fexceptions FORCE EXCEPTIONS
#-fnon-call-exceptions FORCE EXCEPTIONS TO ONLY BE RETURNED BY THE SYSTEM
(MEMORY AND FPU INSTRUTIONS FOR EXAMPLE)
#-fstack-check FORCE STACK CHECKING (DS / 3DS USE AWKWARD STACK
IMPLEMENTATION)
CFLAGS=-march=$(PROCESSOR) -static -fexceptions -fnon-call-exceptions -fstack-check
ALL:
$(CC) $(CFLAGS) $(FILES) -c
.c.o:
$(OBJC) $(OBJREFS) $(OBJECTS) $(NAME)
.cpp.o:
$(OBJC) $(OBJREFS) $(OBJECTS) $(NAME)
You are probably not calling the right gcc. You seem to be calling the gcc installed in your system, rather than the one that comes with the 3DS SDK.
It appears the problem is with -march=arm7tdmi.
I think the workaround is to avoid using -march=arm7tdmi; and use -march=cpu-type, where cpu-type is one of the ones listed at 3.17.4 ARM Options of the GCC manual.
Here's part of the page:
-march=name
This specifies the name of the target ARM architecture. GCC uses this name to determine what kind of instructions it can emit when
generating assembly code. This option can be used in conjunction with
or instead of the -mcpu= option. Permissible names are: ‘armv2’,
‘armv2a’, ‘armv3’, ‘armv3m’, ‘armv4’, ‘armv4t’, ‘armv5’, ‘armv5t’,
‘armv5e’, ‘armv5te’, ‘armv6’, ‘armv6j’, ‘armv6t2’, ‘armv6z’,
‘armv6kz’, ‘armv6-m’, ‘armv7’, ‘armv7-a’, ‘armv7-r’, ‘armv7-m’,
‘armv7e-m’, ‘armv7ve’, ‘armv8-a’, ‘armv8-a+crc’, ‘iwmmxt’, ‘iwmmxt2’,
‘ep9312’.
Is there a way to force '-m64' not overriding CXXFLAGS/CFLAGS. I want automatic x64 build environment like in Linux/BSD amd64.
Why do I need this?
The problem is complexity of the project I need to be buit as x64 on Solaris. It contains several parts and each may use specific C/C++ compiler flags. So, I can't just run:
CXXFLAGS=-m64 O2 ...
CFLAGS=-m64 -O2 ...
./configure
because there are no common C/C++ flags.
All I need is the way to transparently append '-m64' to every gcc/g++ call.
You can write a wrapper (eg: ~/bin/gcc) that would add the required option(s) and put ~/bin first in your PATH. eg:
#!/bin/ksh
/usr/sfw/bin/gcc -m64 "$#"
CPPFLAGS is used for the c preprocessor. It should be picked up by both gcc and g++.
Reference: http://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html