LINUX.ORG.RU

Сборка программы: не так легко как предполагалось (

 , ,


0

1

Добрый день! мне нужно собрать программу прикладного уровня написанную на СИ с неким #define определением, зависящим от текущего ядра системы, для которой компилируется данная программа.
Код ядра, над которым сейчас произвожу тесты, находится в
/usr/src/linux-source-3.2.0
В исходниках ядра в: include/linux/version.h
Определена: #define LINUX_VERSION_CODE 197155
Мне нужно в зависимости от значения данной константы, сделать define определение для моей константы TMP_CONST

В своём коде я пишу следующее:

#if (LINUX_VERSION_CODE == KERNEL_VERSION(3,2,0))
  #define TMP_CONST  1234 // вот этой константе присваивается некое значение в зависимости от ядра (в данном случаем 1234)
#endif

Как сделать подобное? как сделать чтоб код работал универсально, для любого ядра?
Тоесть я начинаю компилировать код прикладной программы, а она автоматически берёт LINUX_VERSION_CODE из кода ядра системы и на основании этого значения, далее присваивает моей константе, верное значение. Как-же мне сделать так, чтоб при сборке брался этот LINUX_VERSION_CODE ?

Deleted

Тоесть я начинаю компилировать код прикладной программы

В прикладных программах такой финт делать нельзя. Морального права нету у этичного программиста.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от quiet_readonly

Да какой же я этический программист?
Надо такой функционал сделать, иначе никак нельзя. Прежде чем тему создавать я голову изрядно поломал, как можно без этого обойтись. Но оказалось никак... Либо до чёртиков отвратительного, не удобного кода сделать. Либо по человечески, - так как описано выше.

Deleted
()
Ответ на: комментарий от Deleted

linux-kernel-headers, а версию ядра можно узнать, запуская uname -r из скриптов сборки.

И тем не менее, желательно определять версию ядра в рантайме. Либо вовсе не привязываться, благо все вызовы ядра обратно совместимы и всегда были таковы.

quiet_readonly ★★★★
()
Последнее исправление: quiet_readonly (всего исправлений: 1)
Ответ на: комментарий от quiet_readonly

Насчёт рантайма, не подходит.
Нужно именно во время сборки делать.

А про скрипты сборки, у меня ни одного не написано, я хз как их правильно написать.
Не подскажите, как должен выглядеть скрипт который будет успешно решать мою проблему?

Deleted
()
Ответ на: комментарий от Deleted

Как уже сказали — uname -r или /proc/version и cc -D во время сборки. Например

#if (LINUX_VERSION_MAJOR == 3 && LINUX_VERSION_MINOR == 6)
#define TEST "3.6.*"
#else
#define TEST "?"
#endif

int main() { puts(TEST); }
$ cc -D LINUX_VERSION_MAJOR=`uname -r | grep -Po "^(\d)"` -D LINUX_VERSION_MINOR=`uname -r | grep -Po "^\d.\K(\d)"` foo.c
$ ./a.out
3.6.*

-D может какой-нибудь cmake делать.

quasimoto ★★★★
()
Ответ на: комментарий от Deleted

в простейшем виде что-то наподобие

if [ `uname -r` == "версия" ]; then
  MYDEFINE=123;
else
  MYDEFINE=345;
fi

gcc main.c -DMYDEFINE=$MYDEFINE

но я тоже тебе скажу, что это плохой подход. Расскажи, зачем тебе это понадобилось, возможно коллективный разум придумает что-то более толковое

marvin_yorke ★★★
()
Последнее исправление: marvin_yorke (всего исправлений: 3)
Ответ на: комментарий от quasimoto

Боюсь показаться глупым. Но
-D LINUX_VERSION_MAJOR=`uname -r`
что делает? при компиляции определяет константу с названием LINUX_VERSION_MAJOR и значением равным версии ядра?
И ещё, за одно поинтересуюсь. Есть ли хорошие учебники или подробная документация по использованию make, cmake ? (в нете находил поверхностную информацию..из которой мало чему научиться можно)..наверняка есть) посоветуйте чтонить почитать по этой теме.

Deleted
()
Ответ на: комментарий от marvin_yorke

Сейчас пробовал пояснение отписать, но вышло громоздко и бестолково. Пояснение только запутывает. В кратце если пояснить, то программа прикладного уровня, сканирует исходный код другой программы, и формирует исходный код нового модуля, для разных версий ядра linux.
Вопрос темы, задавал для того чтоб, процесс сего деяния, не запутывать ещё больше, и упростить..чтоб всё было логично и понятно мне.

Deleted
()
Ответ на: комментарий от quasimoto

Код ядра, над которым сейчас произвожу тесты, находится в

Тогда ещё так:

#include <linux/version.h>

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
#define TEST "3.6.*"
#else
#define TEST "?"
#endif

int main() { puts(TEST); }
$ cat /usr/src/linux/include/linux/version.h
#define LINUX_VERSION_CODE 198154
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
$ cc -I/usr/src/linux/include foo.c

если он точно там находится.

В Gentoo, например, принято смотреть в /usr/src/linux при сборке.

quasimoto ★★★★
()
Ответ на: комментарий от Deleted

при компиляции определяет константу с названием LINUX_VERSION_MAJOR и значением равным версии ядра?

Да

$ uname -r
3.6.10-2.fc16.x86_64
$ uname -r | grep -Po "^\d"
3
$ uname -r | grep -Po "^\d.\K(\d)"
6
$ cc -D LINUX_VERSION_MAJOR=`uname -r | grep -Po "^(\d)"` -D LINUX_VERSION_MINOR=`uname -r | grep -Po "^\d.\K(\d)"` foo.c
# будет раскрыто (там где ``) и выполнено
$ cc -D LINUX_VERSION_MAJOR=3 -D LINUX_VERSION_MINOR=6 foo.c
# дальше препроцессор сделает из foo.c
$ cc -D LINUX_VERSION_MAJOR=3 -D LINUX_VERSION_MINOR=6 -E foo.c
# такое, то есть использует эти LINUX_VERSION_MAJOR и LINUX_VERSION_MINOR переданные аргументами cc
# для, собственно, препроцессинга

Есть ли хорошие учебники или подробная документация по использованию make, cmake ?

Ничего лучше англоязычного выхлопа гугла я не порекомендую :)

quasimoto ★★★★
()
Ответ на: комментарий от Deleted

Не подскажите, как должен выглядеть скрипт который будет успешно решать мою проблему?

Я бы начал с `man make` на вашем месте.

Но вопрос: какой толк от версии ядра, на которой собиралась программа? Учебные цели?

KennyMinigun ★★★★★
()
Ответ на: комментарий от Deleted

Всем ОГРОМНОЕ СПАСИБО за потраченное на помощь мне время!!!
Тему можно закрывать. Ещё раз СПАСИБО!

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.