Ясно, что ему что-то не то передаётся, но я со своими скудными знаниями никак не разберусь (rpath несколько раз пытался по разному указывать, безрезультатно).
Поломался тулчайн GCC (от serge). По крайней мере под Win32
1. На SVN в LIB нет библиотек Libc для статической линковки.
2. Пересобрать newlib не получается - не компилируется crt\setjmp.s
Я в гнусном ассемблере никак.
3. При динамической линковке недостача объектника __main
$(LD) $(LDFLAGS) $(LIBPATH) -o hello $(OBJECTS) -lc.dll -lapp -lgcc_eh
Так и не понял, кто функцию требует, тем не менее при созданной заглушке helloworld работает
4. Нет собранной stdlib++. Она собирается, но при линковке с ней не хватает уже прилично функций
__main - аналогичная проблема,
getc - сделан макросом а библиотека хочет функцию,
__umoddi3 и __udivdi3 - это генерируется при операциях с long long но реализации нет,
strxfrm - не реализована
Хотя эти функции и не вызываются, но cout << "helloworld" не работает
libgcc.a я не нашел ни в каком виде, ни в исходниках, ни в lib. Посчитал, что -lgcc_eh - ее замена с поддержкой исключений
пишет что то про формат
Spoiler:as -o crt/setjmp.o crt/setjmp.s
crt/setjmp.S: Assembler messages:
crt/setjmp.S:27: Error: junk at end of line, first unrecognized character is `('
crt/setjmp.S:28: Error: junk at end of line, first unrecognized character is `('
crt/setjmp.S:29: Error: invalid character '(' in mnemonic
crt/setjmp.S:30: Error: invalid character '(' in mnemonic
crt/setjmp.S:34: Error: no such instruction: `sym (setjmp):'
crt/setjmp.S:37: Error: too many memory references for `mov'
crt/setjmp.S:40: Error: junk `(ebp)' after expression
crt/setjmp.S:40: Error: too many memory references for `mov'
crt/setjmp.S:42: Error: too many memory references for `mov'
crt/setjmp.S:43: Error: too many memory references for `mov'
crt/setjmp.S:44: Error: too many memory references for `mov'
crt/setjmp.S:45: Error: too many memory references for `mov'
crt/setjmp.S:46: Error: too many memory references for `mov'
crt/setjmp.S:48: Error: junk `(ebp)' after expression
crt/setjmp.S:48: Error: too many memory references for `mov'
crt/setjmp.S:49: Error: too many memory references for `mov'
crt/setjmp.S:51: Error: junk `(ebp)' after expression
crt/setjmp.S:51: Error: too many memory references for `mov'
Не удивительно, потому, что файл должен компилироваться gcc.
Вечером гляну поправить makefile
Единственное, я ручками с соурфорджа докачивал недостающие dll для тулчейна Spoiler:libcharset-1.dll
libgcc_s_dw2-1.dll
libgmp-10.dll
libiconv-2.dll
libintl-8.dll
libmpc-3.dll
libmpfr-4.dll
zlib1.dll
mingw32-make.exe тоже приблудный
D:\VSProjects\msys-kos32-4.8.2\win32>mingw32-make.exe --version
GNU Make 3.82
1. libgcc.a действительно, нашелся - валялся внутри каталога компилятора, только не в путях поиска библиотек
Пришлось скопировать ручками
2. Правка makefile для компиляции .S с помощью gcc помогла собраться Libc
Итого С-программы работают, причем получаются компактными.
Правда, на чуть более сложной программке обнаружилось пару мелких багов в CRT
Spoiler:-fopen не знает про текущий каталог запуска программы - нужно указать полный путь
-clock()/CLOCKS_PER_SEC выдает несоответствующие значения
После догрузки необходимых unixtools даже удалось собрать и stdlibc++
Для __main, getc, strxfrm - поставлены заглушки.
__main раньше существовала как пустышка в crt3.c, но почему то была удалена. Она вызывается компилятором при старте main().
Остальные пока не вызываются.
Тем не менее, на обычной
cout << "Hello C++ world!" << endl;
вылетает.
Отладчик показал, что внутри ostream-inst.cc передается нулевой указатель.
Нужно смотреть с отладочной версией библиотеки. Позже гляну, возможно требуется явно инициализировать cout,
1. libgcc.a действительно, нашелся - валялся внутри каталога компилятора, только не в путях поиска библиотек
У остальных таких проблем не возникает. Это намекает на то, что сперва тулчейн надо корректно установить.
-fopen не знает про текущий каталог запуска программы - нужно указать полный путь
Это проблема не fopen, а файловых менеджеров Kolibri. Рекомендую запускать из Shell.
__main находится в libgcc. Эта функция вызывает конструкторы статических объектов. Ставить на ней заглушку facepalm
Необходимо перед запускам сменить рабочую директорию на директорию с которой запускается программа?
Нет, процессы наследуют рабочий каталог родителя. Только разработчики файловых менеджеров об этом забыли. А файловые функции используют рабочий каталог, если не указан полный путь. В результате если запустить shell и выполнить
cd /kolibrios
test
то рабочим каталогом test будет /kolibrios, а точнее примонтированная директория.
А если запустить test в kfar рабочим каталогом скорее всего будет /rd/1
Подтверждаю. Проблема была в замещенном __main().
Также подтверждаю, что из командной строки текущий каталог в fopen корректный.
Со статически слинкованной libc запускается. Но бинарник получился больше ~118Кб после KPack и 375k неупакованный
Попробовал для уменьшения, чтобы сошлось размером с serge, слинковать с динамической clib.dll - не запускается.
$(LD) $(LDFLAGS) $(LIBPATH) -o hellocpp $(OBJECTS) -lstdc++ -lsupc++ -lgcc_eh -lc.dll -lapp -lgcc
clib.dll Положил рядом с программой.
Или я не так собрал или clib.dll должен быть именно в системном rd/1/lib?
Надо повспоминать и задокументировать ньюансы тулчейна с mingw. Их снаружи не всегда видно, но системщики должны знать:
-он загадочным образом ищет свои (дефолтные) хидеры и библиотеки внутри своего подкаталога
-своеобразно генерирует код - 64-int операции, инициализация статических [только ли?] объектов, исключения
-важен порядок указания библиотек при линковке
-линкер не предупреждает о дублирующихся символах
-не всегда корректно обрабатываются перенаправление ввода-вывода у утилит
-в newlib stderr выводит сообщения не на консоль, а на системную доску отладки. perror() тоже
-часть функций clib реализованы как intrinsic
-чтобы не создавался еще один процесс с консольным окном для граф проги нужно добавить линкеру: LDFLAGS+= --subsystem windows
Выкладываю урезанный контроль стека. Описание
---Русский---
Spoiler:Используя продвинутые методики, GCC свободно адресует регистр SP вместо BP для адресации.
Если использовать неверный вызов ассемблерной функции, которые обычно используются в KolibriOS, стек будет несбалансирован.
Если при отладочном режиме адресуется стандратный стек фрейм через BP, то в релизной версии ошибки возникнут даже при обращении к локальным переменным. Чтобы помочь отслеживать такие ситуации, необходимо использовать опции компилятора -fstack-protector-all или -fstack-protector.
Линкеру необходимо добавить в список ssp.o
Исходный код ssp.c прилагается, он должен компилироваться без -fstack-protector
--- ENGLISH ---
Spoiler:Using advanced techniques, GCC free address register SP instead of BP to address.
If you use the wrong call an assembly function that are commonly used in KolibriOS, the stack will be imbalanced.
If debug mode is addressed standratny stack frame by BP, in the release version of any error even when accessing local variables. To help keep track of such situations, you need to use the compiler option -fstack-protector-all or -fstack-protector.
To linker list must be added ssp.o
Ssp.c source code is included, it should compile without -fstack-protector
При определении порчи стека, программа завершится аварийно с выдачей сообщения на доску отладки. Если конечно не произойдет нарушения защиты до выхода из функции.