g++ flag to only check syntax? - c++

Is there a way to have g++ check for C++98 syntax when compiling but at the same time compile as if no -std= has been given ? My goal is to make sure that my source code stays C++98 but I don't want to prevent g++ from using any newer optimisation or trick. For the moment, I compile my projet twice, once with CXXFLAGS=-std=c++98 and one with a final empty CXXFLAGS for release.
It looks like gcc 5 will have -Wc90-c99-compat and -Wc99-c11-compat, that something in that direction.

You will have to run the compiler twice, but you can save compiletime
on the -std=c++98 pass and avoid generating unwanted object files by specifying syntax-checking only. You do that by
passing the option -fsyntax-only.
You'd also need to modify your make to skip linkage for C++98, as there'll be nothing to link.
Probably the most efficient way you could do this is with a make on the
following lines:
.phony: all clean
SRCS = foo.cpp
FLAT_SRCS = $(patsubst %.cpp,%.ii,$(SRCS))
OBJS = $(patsubst %.ii,%.o,$(FLAT_SRCS))
%.ii: %.cpp
g++ -std=c++98 $(CPPFLAGS) -E $< > $# && g++ -std=c++98 -fsyntax-only $#
%.o: %.cpp
%.o: %.ii
g++ -c -o $# $(CPPFLAGS) $(CXXFLAGS) $<
all: foo
foo: $(OBJS)
g++ -o $# $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LDLIBS)
clean:
rm -f $(OBJS) $(FLAT_SRCS) foo
Here, the %.ii: %.cpp rule will first just preprocess the .cpp to the .ii,
then pass the already preprocessed source to a C++98 syntax-checking pass,
which produces no new file.
The empty %.o: %.cpp rule overrides the implicit rule that would otherwise
cause the .cpp to be compiled to .o, and it is replaced with the %.o: %.ii
rule to compile the .ii. g++ recognises .ii as denoting already-preprocessed
C++ source code, so it will not preprocess the source a second time.
Code is only preprocessed once, and object code is only generated once.
The linkage is as usual. Provided the C++98 syntax check passes, a make will look like:
$ make
g++ -std=c++98 -E foo.cpp > foo.ii && g++ -std=c++98 -fsyntax-only foo.ii
g++ -c -o foo.o foo.ii
g++ -o foo foo.o
rm foo.ii
You'll note that make automatically deletes the preprocessed .ii, which is fine:
it's just a conduit between the .cpp and the .o.
All that being said, I side with #Matt McNabb's observation that you have nothing to
gain by this! Given your code is C++98, the compiler won't optimize it any better
when instructed that it must be C++98 than when not. By time GCC gets to the
optimization stage of its business, it no longer cares what kind of source code
it started off with.
You may be supposing that -std=c++98, when given say to g++ 4.x, causes the
whole compiler to behave as if was g++ 2.x. Not so. It's still g++ 4.x, with the
g++ 4.x optimization tech, etc., just operating by the language definition of C++98.
There would certainly be a point in this if your code for some reason had to pass,
as C++98, on some older compiler than your release compiler, and in that case you
would need to distinguish the compilers in the makefile. But apparently this is not the
case. You might as well just compile conventionally with -std=C++98

Related

How to write makefile for a target that includes a header file?

I have two files "create-exercise.cpp" and "exercise.hpp". I want to write a makefile to use gnu++17 and g++ to compile them. exercise.hpp is included in create-exercise.cpp. I only want to get a binary out of create-exercise.cpp. the command I would use is g++ -std=gnu++17 create-exercise.cpp -o create-exercise and it works well. I tried using the following in a make file.
CXXFLAGS=-Wall -std=gnu++17
create-exercise: create-exercise.cpp exercise.hpp
but that generated the following g++ -Wall -std=gnu++17 create-exercise.cpp exercise.hpp -o create-exercise I don't want exercise.hpp to be included in the compilation command. I also tried to use the following instead.
CXXFLAGS=-Wall -std=gnu++17
create-exercise.o: create-exercise.cpp exercise.hpp
That generated g++ -Wall -std=gnu++17 -c -o create-exercise.o create-exercise.cpp. I don't want the -c flag. because when I try to run create-exercise.o that results in permission denied error. I tried the following as well:
CXXFLAGS=-Wall -std=gnu++17
create-exercise.o: create-exercise.cpp exercise.hpp
$(CXX) $(CXXFLAGS) create-exercise.cpp -o create-exercise.o
but when I edit exercise.hpp make says 'create-exercise.o' is up to date. and doesn't recompile it. what should I do?
The rule to write in your makefile would be:
create-exercise.o: exercise.hpp
This is a rule without a recipe, and it simply adds one more prerequisite (exercise.hpp) to the target create-exercise.o, i.e., whenever exercise.hpp changes, create-exercise.o should be rebuilt.
However, the problem when providing that rule is that GNU Make assumes create-exercise.o is an object file generated from a C source file when building create-exercise. Therefore, it doesn't link the C++ library but the C library instead, that's why you are having the liking error of undefined reference to std::cout.
GNU Make has the following implicit rule for generating an executable from a C++ source file:
%: %.cpp
# commands to execute (built-in):
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
You can use that rule's recipe to build create-exercise from creating-exercise.o and still treat creating-exercise.o as an object file that was generated from a C++ source file:
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
The whole makefile would be then:
CXXFLAGS = -Wall -std=gnu++17
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $#
create-exercise.o: exercise.hpp
The target create-exercise also becomes the default goal because it's the first rule in the makefile. It's the target to build if you don't specify any to make.
You can do this:
CXXFLAGS = -Wall -std=gnu++17
create-exercise: create-exercise.o
$(LINK.cpp) $^ $(LDLIBS) -o $#
create-exercise.o: exercise.hpp
This says: build create-exercise from the object file create-exercise.o, if it's changed. And it says rebuild create-exercise.o if the header file exercise.hpp changes; it's not right to modify or rebuild a source file if a header changes. It's the object file that depends on the header.
Make has a number of built in rules. Among them are rules that know how to link a program but unfortunately that assumes your object files were built from C files, so if you're using C++ you have to create a specific recipe. But you can still use GNU make's default variables.
It also knows how to build a .o file from a .cpp file on its own: you don't need to write that recipe.
I am not sure, but maybe try to include the .hpp file instead of compiling it with the other file. You can do so by using g++ *.cpp -I *.hpp -o output
Try it out and let me know if it works for you.

compiling h file doesn't always show errors

If I have an error on line 1, and I comment out the entirety of the H file, it doesn't always.. update?
It seems to be compiling a past version of the .h file, but if i intentionally put an error in the main.cpp file, then it realizes there are errors in the h file. Also it DOES sometimes show the errors that are just in the h file, but idk if it is after a certain period of time has elapsed
I would just try to put my code in a cpp file attached to the header, but the issue with that is the ugliest error i've ever seen and I'd rather it all stay in the header anyways since it'll only be like 15 lines of code.
Here's the makefile i'm using in case there is some weird thing in this causing the delay.. but I've had this issue just using raw "g++ *.h *.cpp" commands before, so that is probably not the issue. I've struggled with this issue for a long time now and had to put my last HW assignment all in one file because of it
MAINPROG=assignment01
CC=gcc
CXX=g++
CPPFLAGS=-g -std=c++11
LFLAGS=
CFLAGS=-g
TARGET=$(MAINPROG)
CPPS=$(wildcard *.cpp)
LINK=g++ $(CPPFLAGS)
OBJS=$(CPPS:%.cpp=%.o)
%.o: %.cpp
$(CXX) $(CPPFLAGS) -MMD -o $# -c $*.cpp
all: $(TARGET)
$(TARGET): $(OBJS)
$(LINK) $(FLAGS) -o $(TARGET) $^ $(LFLAGS)
clean:
-/bin/rm -rf *.d *.o $(TARGET)
As πάντα ῥεῖ says, it's not normal to compile header files directly. They are incorporated into the compile when they are included into the cpp source.
Your makefile also does not link with the library stdc++ (libstdc++.a). I don't know if this is a problem when linking with g++, but it always is for me with gcc.
Oh, and rm -rf to cleanup! That's fairly aggressive, maybe just rm -f would be better, just in case someone accidentally puts / or .. as the target.
I think you should compile on the command line first, and then sort out the problems with your makefile. It might be worth posting copies of your code.
Generally I will compile simple code with:
gcc -g -Wall -o assignment01 assignment01.cpp -lstdc++
This gives: an exe named "assignment01", with debug info, all warnings, and links with c++ std libs.

Is it possible to perform differential linking?

I have a binary which is linked using a large number of object files with many interdependencies. Whenever I recompile even one of these, I need to link the entire binary.
Do linkers (specifically, those of GCC or Clang) support some method of "differential linking", in which enough information is kept about the inter-relations between all the other linked parts, so that the only work that needs to be done when a single part is recompiled is its relations to the other parts + putting them together in the binary?
Note: I'm mostly interested in C++ but I guess this question generalizes at least to C and probably to other compiled languages.
In MSVC this is called "incremental linking". Interestingly, what I've found that GCC might support that to some extent, try using the "-Wl,-i" or "-Wl,-r" parameters to GCC (should be actually also supported by CLang, as these "-Wl" parameters are just passed to ld).
I never used it before, but I made this work with the following makefile:
OBJS := a.o b.o c.o main.o
all: test_app
test_app: test_app.reloc
g++ -o $# $^
# build a "relocatable" object for incremental linking (either -i or -r)
test_app.reloc: $(OBJS)
g++ -Wl,-i -nostdlib -nostartfiles -o $# $^
$(OBJS): makefile
%.o: %.cpp
g++ -c -o $# $<
This builds the app, but I'm not entirely sure what it does internally, if it really does something like "incremental linking" done in MSVC.
In particular, the parameter "-nostdlib" is necessary when using the "-Wl,-i" so that the default libs will not be passed to the ld (which then can't find them - without it I had the error "/usr/bin/ld: cannot find -lgcc_s").
Another version which might actually work better (not sure, this would need to be tested on a bigger application to see if there is some gain in the link time for single object updates):
OBJS := a.ro b.ro c.ro main.ro
all: test_app
test_app: $(OBJS)
g++ -o $# $^
%.o: %.cpp
g++ -c -o $# $<
%.ro: %.o
g++ -Wl,-i -nostdlib -nostartfiles -o $# $<
Basically creating relocatable file for each object (which might be perhaps a significant portion of the linkage of obj files into the executable) and then just updating the relocatables necessary. For the final link step using the relocatables to link everything together (but part of the linkage has been already done before).
It is also possible to create "groups" of object files to be grouped in a single relocatable, so that there will be less of them at the end (not sure if that would bring anything at the end though).

Easy way to build objects for target and x86 at the same time

Currently, this is how I build my object files for my x86 compiler.
CC=g++
%.o: %.cpp
$(CC) $(CFLAGS) $(INCPATH) $(LIBPATH) -DPC -c $^ -o $#
How can I easily switch between g++ and my cross compiler? How can I compile both x86 and binaries for my target at the same time? I seem to be limited to compiling with only one compiler right now. Is there a way to come about this without having to list all my object files one by one?
You could pass the tool chain while giving make
Just an extra variable CROSS_COMPILE would do that
The makefile would rather look like this
CROSS_COMPILE :=
CC=$(CROSS_COMPILE)g++
%.o: %.cpp
$(CC) $(CFLAGS)$(INCPATH) $(LIBPATH) -DPC -c $^ -o $#
So if u just give make then CC is used as g++ and get compiled for x86, if you give make CROSS_COMPILE=arm-none-linux-gnueabi- then it would be compiled for ARM
You can use whatever the tool chain you want the concept remains the same
Sagar's answer does address how to switch between compilers, but does not address how to both do that and the main part of the question, which is how to do both targets at the same time.
To do both targets at the same time, you probably want to separate the objects into directories related to the compiler or target used, and then based on the directory of object, figure out what compiler to use.
So, something like below, in the simplest case, where the sources are in current directory, and the directory is the same as the compiler name. Fill in the user-defined COMPILER function with how you like to calculate your compiler name, based on the directory of the object file, which is the argument $1 to the function.
define COMPILER
$1
endef
.PRECIOUS: %/.
%/.:
mkdir -p $#
.SECONDEXPANSION:
%.o: $$(notdir $$*.cpp) | $$(#D)/.
$(call COMPILER, $(#D)) -c $< -o $#

makefile auto removing .o files

I am taking a C++ course in college and they want us to manually type in all of the test files... I know, however, that there is a way to do it with out, which is how I ended up with the current(http://pastebin.com/6d9UtKM4) makefile. My question is, why is this makefile automatically removing all the .o files it uses for compiling when it is done? It's not killing me, but I would like to preserve the .o files. I have pasted the makefile here(http://pastebin.com/6d9UtKM4). I have also pasted the current result of running "make tests" here(http://pastebin.com/h3Ny3dib). (Note the part at the bottom of that page that removes all the .o files automatically.)
I would also like to be able to make it generate it like this:
g++ -o compileDir/assembler.o -c -Wall src/assembler.cpp
g++ -o compileDir/string.o -c -Wall src/string.cpp
g++ -c -Wall -o compileDir/test_assignment.o testSrc/test_assignment.cpp
g++ -o testDir/test_assignment compileDir/test_assignment.o compileDir/string.o compileDir/assembler.o
g++ -c -Wall -o compileDir/test_bracket.o testSrc/test_bracket.cpp
g++ -o testDir/test_bracket compileDir/test_bracket.o compileDir/string.o compileDir/assembler.o
testDir/test_bracket
testDir/test_assignment
In other words, I want it to compile everything, then run everything. I hope this isn't too much to ask!
Edit: Additional Information: (This is the code that does "make tests")
tests: assembler.o string.o $(test_output) $(test_stringOutput)
#echo '--- Testing complete ---'
$(testDir)%: $(compileDir)%.o string.o
g++ -o $# $< $(compileDir)string.o $(compileDir)assembler.o
$#
#echo ''
$(compileDir)%.o: $(testSourceDir)%.cpp
g++ -c -Wall -o $# $<
$(compileDir)%.o: $(testStringSrc)%.cpp
g++ -c -Wall -o $# $<
EDIT: -----------------------------------------
Resolved via comments:
Adding this line fixed it:
.PRECIOUS $(compileDir)%.o
You might add
.PRECIOUS: %.o
which should be implicit, but perhaps you've got a weird setup.
Make treats your .o files as intermediate and removes them. You can prevent automatic deletion of those by adding them a dependency of the special .SECONDARY target. See Chains of Implicit Rules for more details. Good luck!