gcc/g ++ опция поместить все объектные файлы в отдельный каталог

Я нахожусь в одной лодке; VMware на MBP, делая разработку.NET (и немного Моно, но это - различный зверь). Я рекомендовал бы обновить к бетам Fusion 2.0, если Вы еще не имеете; они быстрее и предлагают некоторые большие новые возможности (несколько снимков! приложение, связывающееся!) и, по моему опыту, так же стабильны как 1.x выпуски.

60
задан 16 December 2009 в 18:43
поделиться

8 ответов

Это урезанный 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)
70
ответ дан 24 November 2019 в 17:41
поделиться

Как насчет перехода в каталог и запуска компиляции оттуда:

cd builddir/objdir
gcc ../../srcdir/file1.c ../../srcdir/file2.c ../../srcdir/file3.c

Вот и все. gcc интерпретирует включения в форме #include "path / to / header.h" как начало в каталоге, в котором существует файл, поэтому вам не нужно ничего изменять.

19
ответ дан 24 November 2019 в 17:41
поделиться

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 {} \;
15
ответ дан 24 November 2019 в 17:41
поделиться

Я думаю, что при сообщении 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 и считаю его очень удобным. Он автоматически генерирует зависимости и имеет другие полезности.

2
ответ дан 24 November 2019 в 17:41
поделиться

Тем временем я нашел «промежуточное» решение, используя параметр -combine.

Пример:

mkdir builddir
mkdir builddir/objdir
cd srcdir

gcc -combine -c file1.c file2.c file3.c -o ../builddir/objdir/all-in-one.o

это «объединяет» все исходные файлы в один объектный файл.

Однако это все еще "наполовину", потому что нужно перекомпилировать все, когда изменяется только один исходный файл.

2
ответ дан 24 November 2019 в 17:41
поделиться

Вы можете использовать простую оболочку вокруг 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 , чтобы включить новую опцию, но это может быть сложно.

11
ответ дан 24 November 2019 в 17:41
поделиться

Это одна из проблем, которые решает autoconf .

Если вы когда-либо выполняли ./ configure && make , вы знаете, что такое autoconf: это инструмент, который генерирует прекрасные сценарии настройки. Не все знают, что вместо этого можно сделать mkdir mybuild && cd mybuild && ../configure && make , и это волшебным образом сработает, потому что autoconf в этом плане великолепен.

configure скрипт создает файлы Makefiles в каталоге сборки . Затем там происходит весь процесс сборки. Таким образом, все файлы сборки естественно появляются там, а не в дереве исходных текстов.

Если у вас есть исходные файлы, выполняющие #include "../banana/peel.h", и вы не можете их изменить, Затем это' Какая боль, чтобы сделать эту работу правильной (вы должны скопировать или создать символическую ссылку на все файлы заголовков в каталог сборки). Если вы можете изменить исходные файлы, чтобы вместо этого сказать #include «libfood / comedy / banana / peel.h» , тогда все готово.

autoconf не совсем прост ], особенно для большого существующего проекта. Но у него есть свои преимущества.

1
ответ дан 24 November 2019 в 17:41
поделиться

Я считаю, что вы поняли концепцию наоборот ...?!

Идея 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 тоже правило.)

5
ответ дан 24 November 2019 в 17:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: