Я решил опробовать CPCC (консольный компилятор Компонентного Паскаля для Линукса, подсистема Блэкбокса).
https://sourceforge.net/projects/cp-dev/Тут я расписываю всё очень подробно в надежде на то, что кому-то в будущем эта писанина поможет разобраться, как пользоваться CPCC. Документация, увы, практически отсутствует.
Долго пытался понять, почему не компилируется проект с тремя файлами, один из которых - внешний модуль. Оказалось, что достаточно этот внешний модуль просто включить в список IMPORT (в другом модуле, где это нужно), а я ещё дописывал его в список LinkedMods в prj-файле:
Код:
LinkedMods=Kernel$+ Math ... Init Out GraphSdl GraphLib GraphTest#
(GraphSdl у меня - это внешний модуль.)
Чтобы скомпилировать этот компонент из трёх файлов, мне потребовалось три PRJ-файла. Иначе оно ругается: "Error #152: symbol file of imported module not found". Порядок сборки такой:
Код:
./cpcc GraphSdl.prj # Тут оно ругается в конце, но без этой строчки никак.
./cpcc GraphLib.prj # Создаётся лишний файл - libgraphlib.so, но без этого тоже никак.
./cpcc GraphTest.prj
Прилагаю к сообщению все 6 файлов (3 cp и 3 prj). Вообще, всё это ненормально. Может, доделаем компилятор-то? Такой компилятор, но доведённый до ума, оказал бы незаменимую помощь при продвижении Оберона в массы.
В итоге, я смог без каких либо дополнительных проблем из линуксовской консоли собрать динамическую библиотеку (SO-файл), экспортирующую процедуру Do модуля GraphTest (кстати, она так и называется - "Do", а не, например, "GraphTest_Do", как было бы в VOC или OO2C, но это, пожалуй, хорошо). Список экспортируемых SO-файлом процедур можно получить командой:
Код:
nm -d libgraphtest.so
Затем я создал файл "prog.c":
Код:
extern void Do();
int main() {
Do();
return 0;
}
и скомпилировал его командой:
Код:
gcc -o prog -lgraphtest -L. prog.c
(-lgraphtest добавляет файл libgraphtest.so, а -L. указывает, что этот файл следует искать также и в текущем каталоге.)
Появился исполняемый файл prog, который замечательно работает, но только запускать его надо вот так:
Код:
env LD_LIBRARY_PATH=. ./prog
или вот так:
Код:
export LD_LIBRARY_PATH=.
./prog
иначе он ругается:
Код:
./prog: error while loading shared libraries: libgraphtest.so: cannot open shared object file: No such file or directory
что очень тупо
Дальше я сделал следующее: в модуль GraphTest (Graph/Mod/Test.cp) добавил секцию BEGIN:
Код:
MODULE GraphTest;
...
BEGIN
Do
END GraphTest.
а из файла "prog.c" убрал всё лишнее, оставив только:
Код:
int main() {
return 0;
}
Это работает, то есть после точно такой же сборки исполняемого файла через GCC программа работает также. Получается, что SO-файл сам запускает процедуру Do внутри себя.
Внимание вопрос. Как сделать так, чтобы SO-файл можно было запускать непосредственно? Или как сделать так, чтобы получался не SO, а ".a"-файл, то есть статическая библиотека?
Или ещё один вариант вопроса: как дописать ElfLinker или LinLinker или что-то ещё и где его взять? Вроде бы, линуксовский SO-файл (имеющий формат ELF) не очень отличается от исполняемого бинарника формата ELF. Пока искал в интернете информацию по этому поводу, с удивлением обнаружил, что некоторые SO-файлы можно даже запускать из консоли после chmod +x и тогда запускается процедура с определённым названием, что-то вроде __ldd_main...