Створення програмного забезпечення для кількох UNIX-платформ, Unix, Операційні системи, статті

Перед початком роботи


Даний посібник присвячено проблемам сумісності при створенні та міграції ваших додатків між різними UNIX-платформами. Замість вивчення відмінностей конкретних платформ ви розглянете прийоми та інструментальні кошти, для того щоб вміти приймати самостійні рішення для досягнення крос-платформної сумісності ваших UNIX-додатків.


Про цей посібник


Розробка програмного забезпечення, яке компілюється і компонується на декількох платформах, може бути складним завданням. Існують незначні й істотні відмінності між різними варіантами UNIX, які можуть бути причинами проблем: від відсутності програм і бібліотек, до відмінностей в заголовних файлах, використовуваних для компонування вашого коду. Облік цих відмінностей робить ваш код більш стерпним, що і є предметом розгляду даного керівництва. Ви також розглянете використання програми GNU autotools, яка може зробити процес міграції та розробки менш болючим і складним.


Попередні умови


Ви повинні мати доступ до компілятору C для роботи з деякими прикладами. Для роботи з програмою autotools необхідний доступ до пакету Autoconf / autotools (див. Web-сайт GNU).


Несумісність UNIX


Причиною появи проблем при компонуванні додатків в UNIX є відмінності в дистрибутивах UNIX, незважаючи на те, що багато з них засновані на стандартних компонентах і поняттях. Розуміння впливу цих відмінностей є першим кроком на шляху створення додатків для різних платформ.


Передумови


Існує декілька різних варіантів UNIX, в тому числі і вільно розповсюджуваних, наприклад, різні BSD-варіанти (Berkeley Systems Division) – FreeBSD, OpenBSD, NetBSD і Linux. Відмінності виникають спочатку з вихідного UNIX-дистрибутива, використовуваного конкретним варіантом UNIX. Існує дві версії: AT & T (розвилася, в кінцевому рахунку, в систему, відому під назвою SVR4) і версія, розроблена в University of California Berkeley (UCB) і відома під назвою BSD-версія.


Різні компанії заснували свої операційні системи UNIX на одній з цих базових редакцій і додали згодом власні розширення і поліпшення. Деякі компанії, зокрема Sun, змінили вихідний варіант, що лежить в основі їх UNIX-системи. Наприклад, компанія Sun замінила BSD-ядро в SunOS на SVR4-ядро в Solaris.


System V Release 4 в даний час є найбільш поширеною в комерційних дистрибутивах і містить ядро, засноване на оригінальному ядрі AT & T з деякими додатковими BSD-елементами.


В результаті, незважаючи на те, що різні версії UNIX (AIX, HP-UX, Solaris та інші) технічно являють собою операційну систему UNIX, відмінності між системами, а саме, відмінності в бібліотеках, заголовних файлах і навіть інструментах для їх компонування, призводять до того, що вихідний код на С не можна просто переносити з однієї платформи на іншу.


Реальні функції незмінні; просто відрізняється місце розташування або визначення функцій.


POSIX-сумісність


Група POSIX виконує величезну роботу по стандартизації різних систем, включаючи операційні системи, службові програми і мови програмування. Стандарти охоплюють широку область і містять все, починаючи від викликів «стандартних» функцій і повертаються ними результатів, до функціональних можливостей OS, на яких ці функції будуть працювати.


Для UNIX первинним POSIX-стандартом є 1003.1, який визначає інтерфейс між додатком і операційною системою.


POSIX-стандарти прийняті в операційних системах багатьох компаній, у тому числі Sun Microsystems, IBM, Digital і Hewlett Packard. Навіть Microsoft надає рівень POSIX-сумісність в Microsoft Windows.


Стандарт POSIX 1003.1 (відомий також як POSIX.1) визначає назви функцій, використовуваних для виконання конкретних операцій в OS, включаючи аргументи, їх формат і порядок виклику. Стандарт також вказує очікуваний результат і всі помилки (і містить стандарти для номерів помилок).


У двох словах, будь-який виклик функції, яка є POSIX-сумісної, повинен працювати на різних операційних системах без будь-яких модифікацій. Наприклад, функція chdir(), Визначена в POSIX-стандарті як int chdir(const char *path); повинна бути доступна у всіх версіях UNIX, є POSIX-сумісні, і значення аргументу (рядок), повертається значення (ціле) і повідомлення про помилки в різних системах повинні бути однаковими.


Якщо створюване вами додаток засноване на конкретної версії UNIX, значить, міграція вашої системи на POSIX-стандарти є першим кроком на шляху до сумісності, хоча це і не усуває всі проблеми.


Оцінка поточної задачі


Вашої першим завданням є визначення складності програми, з якою ви збираєтеся переносити. Звичайне додаток містить багато різних елементів. Ви повинні визначити, які елементи мають бути розроблені заново, а які повинні бути зроблені більш сумісними з різними платформами.


Елементами, які ви повинні дослідити, є:



Природно, основна частина C-коду є переносимої. Більшість сучасних компіляторів З засновані на стандартах, отже компіляція коду не становить проблем. Більша частина проблем при перенесення пов’язана з бібліотеками, заголовками та обмеженнями середовища компонування.


Загальні проблеми


У даному розділі досліджуються деякі основні проблеми, пов’язані з роботою з заголовками, бібліотеками, програмами компонування і середовищем.


Програми компонування і середу


Основними елементами в процесі переносу додатків є доступні інструментальні засоби компонування і середу. Якщо ви використовуєте стандартну програму Makefile, ситуація значно спрощується, але ви все одно повинні брати до уваги деякі критичні відмінності.


Наприклад, повинні бути доступні компілятор C, препроцесор C і такі програми, як yacc, lex та інші. Ви також повинні враховувати параметри командного рядка і процеси для різних інструментальних засобів.


Наприклад, на більшості версій UNIX доступний компілятор C – cc, А також окремий препроцесор C – cpp. Однак для деяких переважно запускати препроцесор з використанням параметра командного рядка -E для cc.


Ви можете спростити середовище і процес, використовуючи вільно поширювані програми, такі як gcc, bison і flex, Але знову ж таки, враховуйте обмеження і відмінності.


Стандартна UNIX-програма yacc, Наприклад, створює файли y.tab.c і y.tab.h (на вимогу), а bison створює файли, засновані на іменах вихідних файлів (наприклад, генерує parser.tab.c з parser.y). Ви повинні враховувати ці відмінності.


Крім того, враховуйте, що різні програми розташовані в різних місцях на різних платформах. Наприклад, Solaris містить make як стандартну програму (але не компілятор C), але вона розташована в каталозі /usr/ccs/bin/make, А не в каталозі за замовчуванням, як на багатьох інших платформах.


Найпростішим способом урахування цих відмінностей на рівні Makefile (без використання програми GNU autotools) є створення окремого Makefile для кожного середовища, змінюючи кожен Makefile відповідно платформі. Потім ви можете використовувати відповідний Makefile в make:






$ make -f Makefile.solaris
 

Вам все одно доведеться враховувати відмінності між файлами, але процес повинен бути значно легше.


Використання препроцесора C


Файли заголовків і більшість архітектурних і функціональних відмінностей зазвичай можуть бути враховані в C за допомогою використання директив препроцесора C для вибору різних ділянок коду.


Система працює, тому що C-код компілюється перед проходом через препроцесор С (cpp). Під час компіляції препроцесор переглядає ухвали і використовує набір порівнюють макросів для визначення наявності (або відсутності) конкретного визначення. Потім ви вказуєте визначення при компонуванні на конкретній платформі.


Ви напевно вже використовували директиви для включення отладочного коду. Наприклад, ви могли б вказати таке визначення при компонуванні програми в середовищі Solaris x86:






#define SOLARISX86
 

Ви можете вказати це визначення або в заголовному файлі, або включити визначення в командний рядок для компілятора:






$ cc -DSOLARISX86
 

Усередині вихідного коду ви могли б тоді вказати коректний фрагмент для використання, перевіряючи це визначення. Наприклад, в лістингу 1 , Вибирається варіант для вашого визначення.


Лістинг 1. Вибір виключення




#ifdef SOLARISX86
/* do solaris specific code */
#else
/* do other Unix code */
#endif

Ви можете також використовувати #ifndef для перевірки того, що директива не була визначена, і #elif для перевірки додаткових директив в секції if..else..endif.


Ви можете використовувати аналогічну систему по всьому вихідного коду. Наприклад, ви можете застосувати її для включення різних заголовних файлів (лістинг 2) І врахувати відмінності, з якими зіткнулися раніше для функції localtime().


Лістинг 2. Вибір файлу заголовка




#ifdef SOLARISX86
#include <iso/time_iso.h>
#else
#include <time.h>
#endif

Ці ж принципи ви повинні використовувати по всьому вашому коду, припускаючи, що ви знаєте, що шукаєте.


Відмінності в заголовках


Найбільш загальною проблемою при перенесенні додатків між різними версіями UNIX є доступні в операційній системі заголовні файли, використовувані для визначення структур, типів змінних і функцій.


Деякі заголовки розміщуються в різних місцях. Наприклад, вміст файлу limits.h більш-менш стандартно в різних UNIX-платформах, але він розташовується в різних каталогах. У AIX, наприклад, ви імпортуєте файл так:






#include <sys/limits.h>
 

Але в Solaris:






#include <limits.h>
 

У деяких ситуаціях, необхідна інформація знаходиться не в тому файлі, відрізняється від використовуваного вами визначення, або зовсім відсутній.


У зазначених ситуаціях ви повинні знайти місце розташування визначення функції, структури або змінної, яку ви шукаєте. Кращим способом пошуку місця розташування є використання програми grep, як показано в наступному коді, в якому шукається визначення PIPE_MAX на системі Solaris.






$ find /usr/include -exec grep -il PIPE_MAX {} ;
/usr/include/sys/param.h
/usr/include/limits.h

Якщо шукане визначення не відповідає визначенню на вихідної платформі, ви можете іноді вставити альтернативне визначення. Однак будьте уважні і не зміните сенс виклику системної або бібліотечної функції; зміна визначення forward-функції змінить відповідну бібліотечну функцію.


Якщо визначення не існує, це може вказувати на відсутність бібліотеки або інтерфейсу, на яких воно базується.


Відмінності в бібліотеках


Різні версії UNIX розміщують компоненти в різних бібліотеках і можуть вимагати включення декількох бібліотек, не потрібних на іншій платформі. Класичним прикладом є мережеві бібліотеки. На багатьох UNIX-платформах необхідні для створення мережевих додатків бібліотеки автоматично включаються в ваші застосування при компонуванні


Проте в Solaris ви повинні явно додати ці бібліотеки, для того щоб вони могли бути пов’язані з вашим додатком:






$ cc -o server server.c -lnsl -lsocket -lresolv
 

Не існує простого способу перерахувати всі різні варіанти і потенційні відмінності для різних версій UNIX. Єдиним способом вирішення цієї проблеми є індивідуальний підхід до кожного з додатком. Пробуйте компілювати програми та слідкуйте за попередженнями про відсутніх символах.


Наприклад, якщо ви не включили бібліотеку math, то можете отримати помилки, аналогічні показаним в лістингу 3.


Лістинг 3. Помилки відсутніх символів




calcparse.tab.o: In function `yyparse”:
calcparse.tab.c:(.text+0x53a): undefined reference to “pow”
calcparse.tab.c:(.text+0x573): undefined reference to “fmod”
calcparse.tab.c:(.text+0x5bb): undefined reference to “log”
calcparse.tab.c:(.text+0x818): undefined reference to “cos”
calcparse.tab.c:(.text+0x829): undefined reference to “tan”
calcparse.tab.c:(.text+0x83c): undefined reference to “cos”
calcparse.tab.c:(.text+0x849): undefined reference to “tan”
calcparse.tab.c:(.text+0x856): undefined reference to “asin”
calcparse.tab.c:(.text+0x863): undefined reference to “acos”
calcparse.tab.c:(.text+0x870): undefined reference to “atan”
collect2: ld returned 1 exit status

Після отримання списку відсутніх символів ви можете переглянути довідковий посібник (man page) на цільової платформі і знайти потрібну бібліотеку.


Для повністю відсутніх функцій, вам можливо доведеться створювати функцію самостійно або надати її з бібліотек сторонніх постачальників. Наприклад, бібліотека GNU glibc містить багато функцій, які можуть бути недоступні у вашій рідній С-бібліотеці системи UNIX, на якій ви працюєте.


При самостійному створенні функції корисно створити один файл з вихідним С-кодом, який містить визначення функції для різних платформ, і потім використовувати показаний раніше прийом з директивами для вибору функцій, призначених для різних платформ.


Відмінності в порядку байт


Крім заголовків файлів і бібліотек існують платформо-залежні відмінності, які, як правило, вирішити значно важче.


Самим фундаментальним з цих відмінностей є порядок байт CPU системи. Порядок байт впливає на спосіб посилання і доступу до рядків, що складається з декількох байт. Причина цього полягає в способі функціонування CPU.


CPU із зворотним порядком байтів (big endian) (SPARC, PA-RISC і PowerPC) звертаються до інформації по порядку, починаючи з найбільш значимого байта. CPU з прямим порядком байтів (little endian) (intel) звертаються до інформації по порядку, починаючи з найменш значимого байта. Це призводить до повного реверсування адреси, наприклад, ABCD в DCBA.


Це не впливає на рядки, оскільки вони засновані на окремих байтах, але впливає на багатобайтові значення, наприклад на 32-бітові адреси, де порядок байтів змінює значення, яке буде відрізнятися в різних типах CPU.


Немає простого вирішення цієї проблеми, але існують способи, при яких ви можете звертатися та зберігати інформацію, не грунтуючись на прямому доступі до багатобайтовим даними, вирішуючи таким чином проблему.


Процеси, сигнали і IPC


Існують незначні відмінності між реалізаціями fork () і потоків в різних версіях UNIX. Наприклад, не всі вони підтримують всі функції fork * (). IRIX підтримує функцію m_fork (), яка фактично більше схожа на одну з різних потокових бібліотек. Однак навіть в області потоків різні реалізації та стандарти не поширені широко.


Різні версії UNIX підтримують різні сигнали. Багато з сигналів ядра залишаються незмінними, наприклад, SIGHUP дорівнює 1, SIGKILL дорівнює NINE; але не покладайтеся на доступність на всіх платформах сигналів, відносяться до операційної системи, таких як SIGJVM1 (Solaris). Зазвичай тільки сигнали зі значеннями до 15 однакові для більшості платформ. Після 15 (SIGTERM) значення сигналів повністю залежать від OS.


Також враховуйте, що методи Interprocess Communication (IPC) не стандартизовані. І хоча більшість версій UNIX підтримує SVR4 IPC, знайте, що немає повного рівня підтримки. Ви повинні зазвичай прив’язуватися до більш відкритим IPC-стандартам, таким як іменовані канали (named pipe).


Використання програми GNU autotools


Єдиною проблемою розглянутих вище підходів є те, що вони вимагають значних зусиль з координації дослідження та організації різних елементів. Вони також вимагають доступу до всіх різним платформам, які ви бажаєте підтримувати, а облік всіх різних варіантів і альтернатив може значно збільшити час розробки.


Огляд програми GNU autotools


Пакет GNU autotools являє собою систему, що формує набір скелетів (skeleton) правил конфігурації і файлів. Коли конфігураційний сценарій виконується на новій системі, він перевіряє операційну систему і вимоги до вихідного коду і формує відповідну конфігурацію заголовків і середовища компонування (на основі стандартного Makefile), яка компонує додаток на системі.


Якщо ви коли-небудь компонували додаток з відкритим вихідним кодом на вашій системі, то можливо пам’ятаєте наступну послідовність:






$ ./configure
$ make
$ make install

Сценарій configure є частиною дистрибутива вихідного коду. Головною перевагою системи autotools є те, що вона може в сценарії визначити конфігурацію і доступність компонентів у системі, на якій виконується сценарій, порівняти з необхідними елементами вихідного коду і сформувати робочу середу компонування.


Весь процес працює, оскільки система autotools грунтується на комбінації заздалегідь відомих значень (наприклад, вона знає доступні на цільовій системі типи, бібліотеки та заголовки) для конкретної платформи, об’єднаної з інформацією про систему часу виконання, визначальною доступність конкретних функцій і заголовних файлів.


Для багатьох додатків ви не повинні робити зміни у вашому коді вручну для того, щоб зробити його стерпним. Також, ви навіть не повинні турбуватися про те, чи працює на цільовій системі сценарій configure. Я розробляв програму, що використовує систему autotools, які успішно компілювалися і компонували без яких-небудь змін в коді на HP-UX, Solaris (SPARC and x86), Linux, Mac OS X і BSD.


Очевидно, що для ефективного використання переваг системи ви, перш за все, повинні надати середовищі autotools звичайний сценарій компонування вашого додатки, а потім використовувати autotools для сканування вашого вихідного коду та визначення функцій, бібліотек та інших компонентів, необхідних для роботи програми.


Налаштування структури проекту


Першою дією при використанні autotools є створення відповідної структури для вашої програми. Для даного прикладу ви будете використовувати простий додаток calculator (див. розділ «Завантаження»), яке базується на компоненті лексичного аналізу (що вимагає наявності lex) і граматичному компоненті (вимагає наявності yacc ), А також на парі інших файлів для підтримки певних операцій. Список файлів наведено в лістингу 4 .


Лістинг 4. Вихідні файли для програми calculator




total 28
-rwxrwx–x 1 mc mcslp 458 Jan 25 17:19 Makefile*
-rwxrwx–x 1 mc mcslp 129 Apr 16 1997 calc.h*
-rwxrwx–x 1 mc mcslp 4216 Jun 11 1997 calcparse.y*
-rwxrwx–x 1 mc mcslp 136 Jun 8 1997 const.c*
-rwxrwx–x 1 mc mcslp 643 Apr 16 1997 fmath.c*
-rwxrwx–x 1 mc mcslp 1095 Jan 25 17:16 lex.l*

Записаний вручну Makefile для компонування програми calculator наведено в лістингу 5.


Лістинг 5. Записаний вручну Makefile




YFLAGS  = -d
PROGRAM = calc
OBJS = calcparse.tab.o lex.yy.o fmath.o const.o
SRCS = calcparse.tab.c lex.yy.c fmath.c const.c
CC = gcc #C compiler
all: $(PROGRAM)
.c.o: $(SRCS)
$(CC) -c $*.c -o $@ -O
calcparse.tab.c: calcparse.y
bison $(YFLAGS) calcparse.y
lex.yy.c: lex.l
flex lex.l
calc: $(OBJS)
$(CC) $(OBJS) -o $@ -lfl -lm
clean:; rm -f $(OBJS) core *~ #* *.o $(PROGRAM) y.* lex.yy.* calcparse.tab.*

Для установки програми на використання з програмою autotools видаліть Makefile, створіть новий каталог (назвемо його calc) і підкаталог (src), в який скопіюйте всі вихідні файли. Схему розташування файлів (готову для autotools) ви можете побачити в лістингу 6.


Лістинг 6. Вихідні файли, готові для компонування з autotools




./calc
./calc/src
./calc/src/calc.h
./calc/src/calcparser.c
./calc/src/calcparser.h
./calc/src/calcparser.y
./calc/src/const.c
./calc/src/fmath.c
./calc/src/lex.c
./calc/src/lex.l

Тепер ви готові почати налаштування вихідних файлів для autotools.


Створення основи Makefiles


Ви повинні створити файл Makefile.am в кожному каталозі з вашими вихідними кодами, в тому числі і в кореневому каталозі проекту. Makefile.am в кореневому каталозі використовується для посилання на вміст інших каталогів. Файли Makefile.am, розташовані в кожному з каталогів з вихідними кодами, використовуються для визначення процесу компоновки і вимог, що ставляться тільки до даного каталогу.


Отже, для вашого прикладу файл Makefile.am в каталозі calc буде виглядати наступним чином:






SUBDIRS=src
 

Цей рядок просто вказує список підкаталогів, що містять файли, які будуть налаштовуватися (і компонуватися) за допомогою системи конфігурування.


Файл Makefile.am у вашому головному каталозі src показаний в лістингу 7.


Лістинг 7. Скелет src / Makefile.am для компонування на цільовій системі за замовчуванням




calcprgdir=../
calcprg_PROGRAMS=calc
calc_SOURCES=lex.l calcparser.y fmath.c const.c
AM_YFLAGS=-d
calc_LDADD=-lfl -lm

Префікс індивідуальних рядків є важливою складовою: він використовується для ідентифікації об’єкта, до якого застосовується параметр.


Перший рядок в лістингу 7 вказує кінцевий каталог програми для його установки програмою make. При компонуванні даного демонстраційного прикладу ми будемо використовувати батьківський каталог в якості цільового для установки.


Другий рядок вказує назву генерується програми. Третя перераховує вихідні файли, необхідні для компонування програми. Зверніть увагу на те, що хоча ваш додаток засноване на С-файлах, автоматично згенерованих різними програмами (зокрема lex або flex і yacc або bison), Вам не потрібно явно вказувати цю стадію. Це є наслідком того, що пакет autotools вже знає, як скомпонувати вихідні файли на мові С з цих вихідних файлів, грунтуючись на їх розширенні.


Четверта рядок встановлює загальний параметр для додавання параметра командного рядка -d при виклику синтаксичного аналізатора yacc. До речі, застосування yacc/bison – Це ще один приклад, де використовується попередньо налаштована обізнаність системи autotools. Autotools знає, що на платформах UNIX може бути встановлений yacc, І якщо це не так, значить встановлена ​​програма GNU bison. Ці дві програми генерують аналогічну інформацію, але в різних файлах; для зручності в програмі bison є режим сумісності з yacc. Коли на системі виконується сценарій configure, Який генерує система autotools для вашого коду, він визначатиме, доступний yacc або bison, І автоматично формувати команду для даного етапу процесу.


Останній рядок лістингу 4 вказує додаткові бібліотеки, необхідні для компонування програми. Зверніть увагу на те, що ви вказуєте тільки назви бібліотек так, як вони вказувалися б для cc; Сценарій configure визначає місце розташування цих бібліотек і необхідність додавання певних каталогів в команду під час компонування програми.


Після настройки основного процесу компоновки ви повинні дати можливість системі autotools просканувати ваш вихідний код і визначити функції та інші елементи, які, можливо, можуть мати різні джерела та визначення в різних системах.


Сканування вихідного коду


Файл configure.ac визначає залежні від конфігурації елементи вашого вихідного коду. Вміст цього файлу використовується для генерування необхідних конфігураційних сценаріїв, які остаточно налаштовують середу компоновки для цільової хост-системи.


Ви не повинні створювати цей файл самостійно; можна використовувати функцію autoscan для автоматичного генерування скелета цього файлу.






$ autoscan
autom4te-2.59: configure.ac: no such file or directory
autoscan-2.59: /usr/bin/autom4te-2.59 failed with exit status: 1

Не звертайте уваги на помилку – вона просто вказує на те, що не був знайдений файл configure.ac, на якому грунтувалася операція сканування. При першому запуску цієї інструментальної програми повинен сформуватися файл під назвою configure.scan. Вміст цього файлу наведено в лістингу 8.


Лістинг 8. Конфігурація autoscan за замовчуванням




# 					-*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([src/calc.h])
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# FIXME: Replace `main” with a function in `-lfl”:
AC_CHECK_LIB([l], [main])
# FIXME: Replace `main” with a function in `-lm”:
AC_CHECK_LIB([m], [main])
# Checks for header files.
AC_FUNC_ALLOCA
AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h stdlib.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
# Checks for library functions.
AC_CHECK_FUNCS([pow])
AC_CONFIG_FILES([src/Makefile])
AC_OUTPUT

Елементи FIXME зручно вказують на те, що саме ви повинні виправити. Перш за все, перейменуйте файл з configure.scan на configure.ac.


Тут необхідно переналаштувати кілька елементів. Почніть з AC_PREREQ і змініть значення таким чином, щоб вони відображали назву пакета, версію та адресу електронної пошти для контактів.


Потім додайте рядок, конфігурується систему для automake:






AM_INIT_AUTOMAKE
 

Необхідно також відновити рядки AC_CHECK_LIB для перевірки конкретних функцій у використовуваних вами бібліотеках. Для цього додатка вам потрібно просто перевірити доступність бібліотеки math ( -lm). Нарешті, ви повинні додати два рядки, що включають визначення конфігурації для запуску lex і yacc, А також файли, які від них залежать.


Одержаний файл повинен виглядати приблизно так, як показано в лістингу 9.


Listing 9. Файл configure.ac




AC_INIT(calc, 1.0, mc at mcslp.com)
AC_CONFIG_SRCDIR([src/calc.h])
AM_INIT_AUTOMAKE
AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
AM_PROG_LEX(src/lex.l)
AC_PROG_YACC(src/calc.y)
# Checks for libraries.
AC_CHECK_LIB([m], [sin])
# Checks for header files.
AC_FUNC_ALLOCA
AC_HEADER_STDC
AC_CHECK_HEADERS([stddef.h stdlib.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
# Checks for library functions.
AC_CHECK_FUNCS([pow])
AC_CONFIG_FILES([src/Makefile])
AC_OUTPUT

Цей файл буде використовуватися програмою autoconf для визначення функцій, які потрібно знайти для компонування програми.


Зміна вихідного коду


Система autotools генерує конфігураційні файли і, що більш важливо, заголовний файл config.h, який використовується для зберігання всіх необхідних елементів визначення для компонування сценарію.


Ви повинні додати заголовний файл config.h у ваші вихідні коди на С, для того щоб вони завантажували інформацію про конфігурацію під час компілювання.


Можливо, ще знадобиться провести незначні зміни в вашому коді. Наприклад, сценарій конфігурування припускає, що yacc-файл calc.y буде формувати два файли, calc.h і calc.c. Перевірте, що при цьому не перезапишуть будь існуючі файли, або просто змініть назву вихідного файлу для yacc.


Створення конфігураційного сценарію


Тепер у вас є скелет Makefile і скелет конфігурації для проекту. Ви повинні перетворити їх в чотири різних компонента:



Цей процес виконується в чотири стадії. По-перше, згенеруйте m4-макрос:






$ aclocal
 

Ви можете проігнорувати будь-які попередження, що видаються цією командою, але зверніть увагу на всі помилки, вони, можливо, вкажуть на помилки в вашому файлі configure.ac. Потім створіть шаблон заголовного файлу:






$ autoheader
 

Тепер ви готові до формування шаблону файлів Makefile. Але спочатку ви повинні створити декілька файлів, що є частиною стандартної конфігурації autotools. Такими файлами є:



Поки ви можете просто створити порожні файли:






$ touch INSTALL NEWS README AUTHORS ChangeLog COPYING
 

Тепер можна створити шаблони Makefile:






$ automake -ac
 

Параметр-a вказує програмі automake додати відсутні файли, а параметр-c – скопіювати ці файли в каталог.


Нарешті, ви повинні згенерувати конфігураційний сценарій, який фактично виконає конфігурування на цільовій системі:






$ autoconf
 

Повна послідовність дій (і приклад відображення результатів роботи) приведена в лістингу 10.


Лістинг 10. Послідовність компоновки конфігурації




$ aclocal
/usr/share/aclocal/pth.m4:43: warning: underquoted definition of _AC_PTH_ERROR
run info “(automake)Extending aclocal”
or see http://sources.redhat.com/automake/automake.html#Extending-aclocal
/usr/share/aclocal/pth.m4:55: warning: underquoted definition of _AC_PTH_VERBOSE
/usr/share/aclocal/pth.m4:61: warning: underquoted definition of AC_CHECK_PTH
/usr/share/aclocal/glib.m4:8: warning: underquoted definition of AM_PATH_GLIB
$ autoheader
$ automake -ac
$ autoconf

Якщо ви перевірите ваш кореневий каталог, то маємо зауважити основні компоненти, такі як сценарій configure, файли config.h.in і Makefile.in (лістинг 11 ).


Лістинг 11. Приклад структури каталогу




-rw-rw-rw- 1 root mcslp 0 Jan 25 15:45 AUTHORS
-rw-r–r– 1 root mcslp 18002 Jan 25 15:45 COPYING
-rw-rw-rw- 1 root mcslp 0 Jan 25 15:45 ChangeLog
-rw-r–r– 1 root mcslp 9498 Jan 25 15:45 INSTALL
-rw-rw-rw- 1 root mcslp 12 Jan 25 15:44 Makefile.am
-rw-rw-rw- 1 root mcslp 18101 Jan 25 16:06 Makefile.in
-rw-rw-rw- 1 root mcslp 0 Jan 25 15:45 NEWS
-rw-rw-rw- 1 root mcslp 0 Jan 25 15:45 README
-rw-rw-rw- 1 root mcslp 31731 Jan 25 15:52 aclocal.m4
drwxr-xr-x 7 root mcslp 238 Jan 25 15:52 autom4te.cache/
-rw-rw-rw- 1 root mcslp 2563 Jan 25 15:52 config.h.in
-rw-rw-rw- 1 root mcslp 2634 Jan 25 15:51 config.h.in~
-rwxrwxrwx 1 root mcslp 174254 Jan 25 15:52 configure*
-rw-rw-rw- 1 root mcslp 690 Jan 25 15:52 configure.ac
-rw-rw-rw- 1 root mcslp 718 Jan 25 15:50 configure.ac~
-rwxr-xr-x 1 root mcslp 15936 Jan 25 15:45 depcomp*
-rwxr-xr-x 1 root mcslp 9233 Jan 25 15:45 install-sh*
-rwxr-xr-x 1 root mcslp 11014 Jan 25 15:45 missing*
drwxrwxrwx 16 root mcslp 544 Jan 25 16:08 src/

Тепер ви можете спробувати сконфігурувати ваш додаток.


Тестування нової конфігурації


Для перевірки конфігурації просто виконайте команду configure. Ви повинні побачити визначення сценарієм різних необхідних файлів бібліотек і заголовків (лістинг 12).


Лістинг 12. Виконання прикладу конфігураційного сценарію




$ ./configure
checking for a BSD-compatible install… /bin/install -c
checking whether build environment is sane… yes
/bin/sh: /mnt/mc/Active: No such file or directory
configure: WARNING: `missing” script is too old or missing
checking for gawk… gawk
checking whether make sets $(MAKE)… yes
checking for gcc… gcc
checking for C compiler default output file name… a.out
checking whether the C compiler works… yes
checking whether we are cross compiling… no
checking for suffix of executables…
checking for suffix of object files… o
checking whether we are using the GNU C compiler… yes
checking whether gcc accepts -g… yes
checking for gcc option to accept ANSI C… none needed
checking for style of include used by make… GNU
checking dependency style of gcc… gcc3
checking for flex… flex
checking for yywrap in -lfl… yes
checking lex output file root… lex.yy
checking whether yytext is a pointer… yes
checking for bison… bison -y
checking for sin in -lm… yes
checking how to run the C preprocessor… gcc -E
checking for egrep… grep -E
checking for working alloca.h… yes
checking for alloca… yes
checking for ANSI C header files… yes
checking for sys/types.h… yes
checking for sys/stat.h… yes
checking for stdlib.h… yes
checking for string.h… yes
checking for memory.h… yes
checking for strings.h… yes
checking for inttypes.h… yes
checking for stdint.h… yes
checking for unistd.h… yes
checking stddef.h usability… yes
checking stddef.h presence… yes
checking for stddef.h… yes
checking for stdlib.h… (cached) yes
checking for an ANSI C-conforming const… yes
checking for pow… yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating src/Makefile
config.status: creating config.h
config.status: executing depfiles commands

Потім ви можете виконати команду make для компонування вашого додатки (лістинг 13).


Лістинг 13. Виконання make




$ make
make all-recursive
make[1]: Entering directory `/export/data/calc”
Making all in src
make[2]: Entering directory `/export/data/calc/src”
bison -y -d calcparser.y
flex lex.l
if gcc -DHAVE_CONFIG_H -I. -I. -I..
-g -O2 -MT fmath.o -MD -MP -MF “.deps/fmath.Tpo” -c -o fmath.o fmath.c;
then mv -f “.deps/fmath.Tpo” “.deps/fmath.Po”; else rm -f “.deps/fmath.Tpo”;
exit 1; fi
sed “/^#/ s/lex.yy.c/lex.c/” lex.yy.c >lex.c
rm -f lex.yy.c
if gcc -DHAVE_CONFIG_H -I. -I. -I..
-g -O2 -MT tmath.o -MD -MP -MF “.deps/tmath.Tpo” -c -o tmath.o tmath.c;
then mv -f “.deps/tmath.Tpo” “.deps/tmath.Po”; else rm -f “.deps/tmath.Tpo”;
exit 1; fi
if gcc -DHAVE_CONFIG_H -I. -I. -I..
-g -O2 -MT const.o -MD -MP -MF “.deps/const.Tpo” -c -o const.o const.c;
then mv -f “.deps/const.Tpo” “.deps/const.Po”; else rm -f “.deps/const.Tpo”;
exit 1; fi
if test -f y.tab.h; then to=`echo “calcparser_H” / sed -e
“y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/” -e “s/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g”`;
sed -e “/^#/!b” -e “s/Y_TAB_H/$to/g” -e “s/y.tab.h/calcparser.h/” y.tab.h >calcparser.ht;
rm -f y.tab.h;
if cmp -s calcparser.ht calcparser.h; then rm -f calcparser.ht ;
else mv calcparser.ht calcparser.h; fi; fi
if test -f y.output; then mv y.output calcparser.output; fi
sed “/^#/ s/y.tab.c/calcparser.c/” y.tab.c
>calcparser.ct && mv calcparser.ct calcparser.c
if gcc -DHAVE_CONFIG_H -I. -I. -I.. –
g -O2 -MT lex.o -MD -MP -MF “.deps/lex.Tpo” -c -o lex.o lex.c;
then mv -f “.deps/lex.Tpo” “.deps/lex.Po”;
else rm -f “.deps/lex.Tpo”; exit 1; fi
rm -f y.tab.c
if gcc -DHAVE_CONFIG_H -I. -I. -I..
-g -O2 -MT calcparser.o -MD -MP -MF “.deps/calcparser.Tpo”
-c -o calcparser.o calcparser.c; then mv -f “.deps/calcparser.Tpo” “.deps/calcparser.Po”;
else rm -f “.deps/calcparser.Tpo”; exit 1; fi
gcc -g -O2 -o calc calcparser.o lex.o fmath.o tmath.o const.o -lfl -lm -lm
make[2]: Leaving directory `/export/data/calc/src”
make[2]: Entering directory `/export/data/calc”
make[2]: Nothing to be done for `all-am”.
make[2]: Leaving directory `/export/data/calc”
make[1]: Leaving directory `/export/data/calc”
You can try out the application just to make it has been built properly:
$ ./src/calc
45*69
3105

Ви можете повернутися в первісний стан (до компонування і конфігурації), використовуючи покажчик distclean:






$ make distclean
 

Використовуючи файли спільно з NFS-з’єднанню і застосовуючи цей метод для «скидання» проекту в початковий стан після кожної компоновки, ви можете легко протестувати процес на кількох платформах без необхідності копіювання дистрибутива на кожну систему.


Обмеження програми autotools


Система autotools бере на себе значну частку складності компоновки сумісних з декількома платформами додатків, але вона не є остаточним рішенням.


autotools не може врахувати спеціалізовані бібліотеки, сторонніх розробників або ваші власні, які не є частиною дистрибутивних файлів (хоча ніщо не заважає вам додати їх або створити спеціалізовані конфігурації autotool).


autotools також не може врахувати будь-які використовуються вами елементи, унікальні для конкретної OS. Якщо використовувана вами функція або бібліотека є унікальною для Solaris (наприклад, унікальна для інтерфейсу ядра Solaris), autotools не зможе вирішити цю проблему.


Система autotools вирішує тільки основні проблеми відмінностей у версіях UNIX і C-бібліотеках, залежності їх заголовків, і середовища компоновки, необхідних для компілювання зв’язків елементів. Вона не може емулювати альтернативну бібліотеку і середу ядра для перенесення програмного забезпечення.


Це не означає, що autotools не можна використовувати; це можливо найефективніша інструментальна програма середовища компоновки для перенесення програмного забезпечення, але не чекайте від неї чудес. Для найбільш ефективного використання autotools ви повинні бути готові комбінувати її використання із застосуванням деяких з розглянутих раніше в цьому посібнику прийомів і методик для забезпечення переносимості.


Нарешті, незалежно від обсягу виконуваної вами роботи, немає реальної заміни тестування вашої програми на цільовій платформі. Програма autotools може спростити процес компонування, але не чекайте від неї виключення необхідності налагодження і тестування.


Резюме


Розробка додатків, що працюють на декількох UNIX-платформах, вимагає розуміння існуючих проблем, які впливають на процеси компілювання і зв’язування. Майже для всіх ситуацій проблеми виникають в двох областях: у заголовних файлах, які підтримують стандартну функціональність системи і ядра, і бібліотеках, використовуваних для підтримки спеціалізованих розширень і функціональності. За цими відмінностями ховаються складні проблеми обмежень конкретної операційної системи. Наприклад, проблеми можуть викликати розбіжності в сигналах, які підтримуються різними версіями UNIX.


Деякі з цих відмінностей можуть бути пом’якшені використанням прийомів для обходу цих відмінностей і проблем. Для спрощення проблем в заголовках, бібліотеках і середовищах компоновки ви можете використовувати пакет autotools / autoconf, вироблений GNU. Він використовує комбінацію відомих відмінностей і сценарій визначення особливостей середовища цільової системи під час процесу компоновки, і, потім, формує відповідний сценарій компонування і заголовний файл для обліку платформо-залежних питань.


Хоча програма autotools може спростити процес компонування, вона не призначена для обліку всіх особливостей платформ. Вона не може, наприклад, врахувати відсутні функції, бібліотеки і відмінності в ядрі OS, але буде враховувати значну частку відмінностей.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*