Я нахожусь в одной лодке; VMware на MBP, делая разработку.NET (и немного Моно, но это - различный зверь). Я рекомендовал бы обновить к бетам Fusion 2.0, если Вы еще не имеете; они быстрее и предлагают некоторые большие новые возможности (несколько снимков! приложение, связывающееся!) и, по моему опыту, так же стабильны как 1.x выпуски.
Это урезанный make-файл для одного из моих проектов, который компилирует исходный код в 'src' и помещает файлы .o в каталог "obj". Ключевым моментом является использование функции patsubst () - подробности см. В руководстве GNU make (которое на самом деле неплохо читается):
OUT = lib/alib.a
CC = g++
ODIR = obj
SDIR = src
INC = -Iinc
_OBJS = a_chsrc.o a_csv.o a_enc.o a_env.o a_except.o \
a_date.o a_range.o a_opsys.o
OBJS = $(patsubst %,$(ODIR)/%,$(_OBJS))
$(ODIR)/%.o: $(SDIR)/%.cpp
$(CC) -c $(INC) -o $@ $< $(CFLAGS)
$(OUT): $(OBJS)
ar rvs $(OUT) $^
.PHONY: clean
clean:
rm -f $(ODIR)/*.o $(OUT)
Как насчет перехода в каталог и запуска компиляции оттуда:
cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c
Вот и все. gcc интерпретирует включения в форме #include "path / to / header.h"
как начало в каталоге, в котором существует файл, поэтому вам не нужно ничего изменять.
A trivial but effective workaround is to add the following right after the gcc call in your Makefile:
mv *.o ../builddir/objdir
or even a soft-clean (possibly recursive) after the compilation is done, like
rm -f *.o
or
find . -name \*.o -exec rm {} \;
Я думаю, что при сообщении pass gcc нет отдельной возможности сказать куда поместить объектный файл, так как он уже есть. Это «-c» - он говорит, в какой каталог поместить объект. Например:
gcc -c file.c -o /a/b/c/file.o --put-object-in-dir-non-existing-option /a1/a2/a3
Вы не можете поместить /a/b/c/file.o в / a1 / a2 / a3, поскольку оба пути являются абсолютными. Таким образом, "-c" следует заменить только на объектный файл.
Я советую вам рассмотреть возможность замены make-файла, например cmake , scons и других. Это позволит реализовать систему сборки как для простого проекта, так и для более крупного.
Посмотрите, например, как легко скомпилировать ваш пример с помощью cmake. Просто создайте файл CMakeList.txt в srcdir /:
cmake_minimum_required(VERSION 2.6)
project(test)
add_library(test file1.c file2c file3.c)
А теперь введите:
mkdir -p builddir/objdir
cd builddir/objdir
cmake ../../srcdir
make
Вот и все, объектные файлы будут находиться где-то в каталоге builddir / objdir.
Я лично использую cmake и считаю его очень удобным. Он автоматически генерирует зависимости и имеет другие полезности.
Тем временем я нашел «промежуточное» решение, используя параметр -combine.
Пример:
mkdir builddir
mkdir builddir/objdir
cd srcdir
gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o
это «объединяет» все исходные файлы в один объектный файл.
Однако это все еще "наполовину", потому что нужно перекомпилировать все, когда изменяется только один исходный файл.
Вы можете использовать простую оболочку вокруг gcc
, которая сгенерирует необходимые параметры -o
и вызовет 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
] Вот такой скрипт gcc_wrap
в его простейшей форме:
#!/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: $!");
}
Конечно, стандартным способом является решение проблемы с помощью Makefile
или проще, с помощью CMake
или bakefile
, но вы специально попросили решение, которое добавляет функциональность к gcc
, и я думаю, что единственный способ - написать такую оболочку. Конечно, вы также можете исправить исходные тексты gcc
, чтобы включить новую опцию, но это может быть сложно.
Это одна из проблем, которые решает autoconf .
Если вы когда-либо выполняли ./ configure && make
, вы знаете, что такое autoconf: это инструмент, который генерирует прекрасные сценарии настройки. Не все знают, что вместо этого можно сделать mkdir mybuild && cd mybuild && ../configure && make
, и это волшебным образом сработает, потому что autoconf в этом плане великолепен.
configure
скрипт создает файлы Makefiles в каталоге сборки . Затем там происходит весь процесс сборки. Таким образом, все файлы сборки естественно появляются там, а не в дереве исходных текстов.
Если у вас есть исходные файлы, выполняющие #include "../banana/peel.h"
, и вы не можете их изменить, Затем это' Какая боль, чтобы сделать эту работу правильной (вы должны скопировать или создать символическую ссылку на все файлы заголовков в каталог сборки). Если вы можете изменить исходные файлы, чтобы вместо этого сказать #include «libfood / comedy / banana / peel.h»
, тогда все готово.
autoconf не совсем прост ], особенно для большого существующего проекта. Но у него есть свои преимущества.
Я считаю, что вы поняли концепцию наоборот ...?!
Идея Makefiles заключается в том, что они обрабатывают только те файлы, которые были обновлены с момента последней сборки, чтобы сократить ( повторное) время компиляции. Если вы объединяете несколько файлов вместе за один запуск компилятора, вы, по сути, не справляетесь с этой целью.
Ваш пример:
gcc -c file1.c file2.c file3.c **--outdir=**../builddir/objdir
Вы не указали правило «make», которое используется в этой командной строке; но если какой-либо из трех файлов был обновлен, вы должны запустить эту строку и перекомпилировать все три файла, что может быть совсем не обязательно. Он также не дает make 'порождать отдельный процесс компиляции для каждого исходного файла, как это было бы при отдельной компиляции (при использовании опции' -j ', как я настоятельно рекомендую).
Я написал Учебник Makefile в другом месте, который включает в себя некоторые дополнительные детали (например, автоматическое определение исходных файлов вместо их жесткого кодирования в Makefile, автоматическое определение включаемых зависимостей и встроенное тестирование).
Все, что вам нужно сделать, чтобы получить отдельный каталог объекта будет заключаться в добавлении соответствующей информации каталога в строку OBJFILES: =
и правило %. o:% .c Makefile
из этого руководства. В ответе Нила Баттерворта есть хороший пример того, как добавить информацию о каталоге.
(Если вы хотите использовать DEPFILES или TESTFILES, как описано в руководстве, вам придется адаптировать DEPFILES: =
и TSTFILES: =
строк плюс %. T:% .c Makefile pdclib.a автоматическое определение включает зависимости и встроенное тестирование).
Все, что вам нужно сделать, чтобы получить отдельный каталог объектов, - это добавить соответствующую информацию о каталоге в строку OBJFILES: =
и ]%. o:% .c Makefile
правило из этого руководства. В ответе Нила Баттерворта есть хороший пример того, как добавить информацию о каталоге.
(Если вы хотите использовать DEPFILES или TESTFILES, как описано в руководстве, вам придется адаптировать DEPFILES: =
и TSTFILES: =
строки плюс %. T:% .c Makefile pdclib.a автоматическое определение включает зависимости и встроенное тестирование).
Все, что вам нужно сделать, чтобы получить отдельный каталог объектов, - это добавить соответствующую информацию о каталоге в строку OBJFILES: =
и ]%. o:% .c Makefile
правило из этого руководства. В ответе Нила Баттерворта есть хороший пример того, как добавить информацию о каталоге.
(Если вы хотите использовать DEPFILES или TESTFILES, как описано в руководстве, вам придется адаптировать DEPFILES: =
и TSTFILES: =
строк плюс %. T:% .c Makefile pdclib.a c Правило Makefile
из этого руководства. В ответе Нила Баттерворта есть хороший пример того, как добавить информацию о каталоге.
(Если вы хотите использовать DEPFILES или TESTFILES, как описано в руководстве, вам придется адаптировать DEPFILES: =
и TSTFILES: =
строк плюс %. T:% .c Makefile pdclib.a c Правило Makefile
из этого руководства. В ответе Нила Баттерворта есть хороший пример того, как добавить информацию о каталоге.
(Если вы хотите использовать DEPFILES или TESTFILES, как описано в руководстве, вам придется адаптировать DEPFILES: =
и TSTFILES: =
строки плюс %. T:% .c Makefile pdclib.a
тоже правило.)