[devel] ccache support in gcc-common

Alexander Bokovoy =?iso-8859-1?q?a=2Ebokovoy_=CE=C1_sam-solutions=2Enet?=
Ср Сен 17 20:13:32 MSD 2003


Greetings!

Предлагаю следующее добавление в gcc_wrapper, которое позволит наиболее
элегантным путем (как мне кажется) интегрировать ccache в сборочные
системы. Дело в том, что в текущий момент времени у нас есть следующие
проблемы с интеграцией в BTE:

1. Мы используем альтернативы для подмены gcc/g++/cpp на ccache так, чтобы
пакеты, которые не умеют смотреть на переменные окружения (например, CC)
работали с ccache.

2. Мы вынуждены прикладывать небольшой патч на ccache, чтобы вычислять,
кого же вызывать для реального выполнения задания (gcc/g++/cpp).

Однако у нас в системе уже есть gcc-common, а в нем gcc_wrapper, который
выполняет вызов архитектурно-зависимого компилятора (i586-alt-linux). 
Делает он следующее:

1. Вычисляет имя архитектурно-зависимого компилятора, по умолчанию считая,
что вызывают gcc (i586-alt-linux-gcc).

2. Если установлена переменная окружения GCC_VERSION, то добавляет к этому
имени указанную версию и %bindir.

3. Вызывает получившуюся программу, передавая ей те же параметры, что и
были получены самим gcc_wrapper.

Что при этом происходит, можно понять по strace:

$ strace -e trace=process gcc_wrapper -V 3.2 -v
execve("/usr/bin/gcc_wrapper", ["gcc_wrapper", "-V", "3.2", "-v"], [/* 49 vars */]) = 0
execve("/usr/bin/i586-alt-linux-gcc", ["i586-alt-linux-gcc", "-V", "3.2", "-v"], [/* 49 vars */]) = 0
Using builtin specs.
gcc driver version 2.96 20000731 (ALT Linux, build 2.96-alt3) executing
gcc version 3.2
_exit(0)

Поскольку ccache работает по похожему принципу, можно вместо запуска
вычисленной программы (%bindir/%targetplatform-<gcc>-$GCC_VERSION)
запускать ccache, подставляя ему в качестве имени программы
архитектурно-зависимое имя компилятора -- i586-alt-linux-gcc-$GCC_VERSION

Получается следующее:

$ GCC_USE_CCACHE=1 strace -e trace=process ./gcc_wrapper -V 3.2 -v
execve("./gcc_wrapper", ["./gcc_wrapper", "-V", "3.2", "-v"], [/* 50 vars */]) = 0
execve("/usr/bin/ccache", ["i586-alt-linux-gcc", "-V", "3.2", "-v"], [/* 50 vars */]) = 0
execve("/usr/bin/i586-alt-linux-gcc", ["/usr/bin/i586-alt-linux-gcc", "-V", "3.2", "-v"], [/* 50 vars */]) = 0
Using builtin specs.
gcc driver version 2.96 20000731 (ALT Linux, build 2.96-alt3) executing
gcc version 3.2
_exit(0) 

То есть, мы производим прозрачный запуск ccache, который уже сам
расправляется с тем, кого же надо будет запустить, по переданному ему
имени программы (i586-alt-linux-gcc в данном случае). Механизм сработает, 
поскольку архитектурно-зависимые компиляторы представляют собой нормальные
исполняемые файлы, а не символические ссылки, управляемые альтернативами.

Заметьте, что в указанном примере я специально использовал опцию -V у gcc
для показа возможности интеграции с gcc-драйвером по вызову компилятора,
отличного по версии от запускаемого. То есть, все возможности
оригинального gcc при этом сохранены, для него все прозрачно -- он даже не
будет знать, что запускается с кэшированием.

Что при этом мы получаем:

1. ccache не требует модификаций.

2. Не требуется модификация альтернатив для подстановки ccache перед gcc.

3. ccache интегрируется в любое окружение, не только в BTE -- достаточно
поставить пакет ccache и выставить переменную окружения GCC_USE_CCACHE.

4. Не возникает ограничений по использованию ccache вместе с distcc на
одной и той же платформе -- в новом ccache (2.2) используется специальный
механизм CCACHE_PREFIX для интеграции с distcc. Если бы мы использовали
этот же подход для интеграции с BTE, то мы бы лишились возможности легко
интегрироваться с distcc и фактически породили бы аналог gcc_wrapper,
запускаемый из ccache.

В чем мы себе отказываем:

А ни в чем :) Запуск компилятора с архитектурой, отличной от архитектуры
по умолчанию, по-прежнему возможен посредством опции -b <machine> в gcc.

Вот патч:

--- gcc_wrapper.c.orig	2002-11-28 14:44:31 +0200
+++ gcc_wrapper.c	2003-09-17 18:31:02 +0300
@@ -14,6 +14,7 @@
 	char *suffix = "", *name, *path;
 	const char *progname = strcmp (__progname, "gcc_wrapper") ? __progname : "gcc";
 	const char *version = getenv ("GCC_VERSION");
+	const char *use_ccache = getenv ("GCC_USE_CCACHE");
 
 	if (version)
 	{
@@ -29,7 +30,7 @@
 
 	if (asprintf (&name, "%s-%s%s", TARGET, progname, suffix) < 0)
 		error (EXIT_FAILURE, errno, "asprintf");
-	if (asprintf (&path, "%s/%s", BINDIR, name) < 0)
+	if (asprintf (&path, "%s/%s", BINDIR, (use_ccache) ? "ccache" : name) < 0)
 		error (EXIT_FAILURE, errno, "asprintf");
 
 	argv[0] = name;

Что нужно кроме него?

1. Убрать поддержку __ccache_cc/__ccache_cxx из rpm-build, они больше не
нужны.

2. Добавить выставление GCC_USE_CCACHE=1 в обработку __ccache_dir в
rpm-build.

Все. После этого исчезнет необходимость существования пакета ccache-bte и
все будет делаться в рамках gcc-common/ccache (без патчей!)/rpm-build.
Для того, чтобы активировать поддержку ccache в RPM надо будет только в
~/.macros поставить:

%__ccache_dir ~/.ccache или любой другой путь

-- 
/ Alexander Bokovoy
---
"He was a modest, good-humored boy.  It was Oxford that made him insufferable."



Подробная информация о списке рассылки Devel