I am wondering why gcc/g++ doesn\'t have an option to place the generated object files into a specified directory.
For example:
mkdir builddir
mkdir
I believe you got the concept backwards...?!
The idea behind Makefiles is that they only process the files that have been updated since the last build, to cut down on (re-)compilation times. If you bunch multiple files together in one compiler run, you basically defeat that purpose.
Your example:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
You didn't give the 'make' rule that goes with this command line; but if any of the three files has been updated, you have to run this line, and recompile all three files, which might not be necessary at all. It also keeps 'make' from spawning a seperate compilation process for each source file, as it would do for seperate compilation (when using the '-j' option, as I would strongly suggest).
I wrote a Makefile tutorial elsewhere, which goes into some extra detail (such as auto-detecting your source files instead of having them hard-coded in the Makefile, auto-determining include dependencies, and inline testing).
All you would have to do to get your seperate object directory would be to add the appropriate directory information to the OBJFILES :=
line and the %.o: %.c Makefile
rule from that tutorial. Neil Butterworth's answer has a nice example of how to add the directory information.
(If you want to use DEPFILES or TESTFILES as described in the tutorial, you'd have to adapt the DEPFILES :=
and TSTFILES :=
lines plus the %.t: %.c Makefile pdclib.a
rule, too.)
You can use a simple wrapper around gcc
that will generate the necessary -o
options and call gcc
:
$ ./gcc-wrap -c file1.c file2.c file3.c --outdir=obj
gcc -o obj/file1.o -c file1.c
gcc -o obj/file2.o -c file2.c
gcc -o obj/file3.o -c file3.c
Here is such a gcc_wrap
script in its simplest form:
#!/usr/bin/perl -w
use File::Spec;
use File::Basename;
use Getopt::Long;
Getopt::Long::Configure(pass_through);
my $GCC = "gcc";
my $outdir = ".";
GetOptions("outdir=s" => \$outdir)
or die("Options error");
my @c_files;
while(-f $ARGV[-1]){
push @c_files, pop @ARGV;
}
die("No input files") if(scalar @c_files == 0);
foreach my $c_file (reverse @c_files){
my($filename, $c_path, $suffix) = fileparse($c_file, ".c");
my $o_file = File::Spec->catfile($outdir, "$filename.o");
my $cmd = "$GCC -o $o_file @ARGV $c_file";
print STDERR "$cmd\n";
system($cmd) == 0 or die("Could not execute $cmd: $!");
}
Of course, the standard way is to solve the problem with Makefiles
, or simpler, with CMake
or bakefile
, but you specifically asked for a solution that adds the functionality to gcc
, and I think the only way is to write such a wrapper. Of course, you could also patch the gcc
sources to include the new option, but that might be hard.
I am trying to figure out the same thing. For me this worked
CC = g++
CFLAGS = -g -Wall -Iinclude
CV4LIBS = `pkg-config --libs opencv4`
CV4FLAGS = `pkg-config --cflags opencv4`
default: track
track: main.o
$(CC) -o track $(CV4LIBS) ./obj/main.o
ALLFLAGS = $(CFLAGS) $(CV4FLAGS)
main.o: ./src/main.cpp ./include/main.hpp
$(CC) $(ALLFLAGS) -c ./src/main.cpp $(CV4LIBS) -o ./obj/main.o
``
This is among the problems autoconf solves.
If you've ever done ./configure && make
you know what autoconf is: it's the tool that generates those nice configure scripts. What not everyone knows is that you can instead do mkdir mybuild && cd mybuild && ../configure && make
and that will magically work, because autoconf is awesome that way.
The configure
script generates Makefiles in the build directory. Then the entire build process happens there. So all the build files naturally appear there, not in the source tree.
If you have source files doing #include "../banana/peel.h"
and you can't change them, then it's a pain to make this work right (you have to copy or symlink all the header files into the build directory). If you can change the source files to say #include "libfood/comedy/banana/peel.h"
instead, then you're all set.
autoconf is not exactly easy, especially for a large existing project. But it has its advantages.