Просмотр полной версии : "Умная линковка" в компиляторах
Oleg N. Cher
09.06.2014, 19:31
Если расставить точки над "i", то вся эта возня нужна лишь для того, чтобы заткнуть дыру в доброй половине компиляторов Си - они запихивают все функции откомпилированного исходника в библиотеку моноблоком, и, соответственно, при использовании хотя бы одной из них - тянутся все остальные.
У меня тоже есть собственное решение - утилита smartlib, включенная в дистрибутив XDev. Она разрезает исходник по "линиям разреза", добавляя к каждому куску заголовок до "линии заголовка" автоматически, и не нужно вручную пихать каждую функцию в отдельный файл.
Именно так построены все существующие на данный момент библиотеки ZXDev (http://zx.pk.ru/showpost.php?p=713748&postcount=235). Скоро сюда добавится библиотека NewSupercode (http://www.worldofspectrum.org/infoseekid.cgi?id=0008509) (я адаптировал для ZXDev пока что только 6 подпрограмм).
Подробнее в теме "Умная" линковка (smart linking) в ZXDev/SDCC (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=34).
Q-Master
09.06.2014, 20:05
Если расставить точки над "i", то вся эта возня нужна лишь для того, чтобы заткнуть дыру в доброй половине компиляторов Си - они запихивают все функции откомпилированного исходника в библиотеку моноблоком, и, соответственно, при использовании хотя бы одной из них - тянутся все остальные.
Редкостная чепуха. Ни один из основных используемых компиляторов на не8-битках при линковании исполняемого файла со статическими библиотеками не тянет все поголовно ф-ции, если они не используются. Не надо проецировать Борландовские поделия на все остальные компиляторы.
Как ведет себя в этом случае сдцц я не в курсе, но подозреваю что такой примитивный вариант оптимизации там осилили. Если не осилили то здравый вариант разбивать на модули с ф-циями объединенными по некоему признаку. В этом случае из статической библиотеки слинкуются только те объектники, которые содержат используемые ф-ции.
Oleg N. Cher
10.06.2014, 00:30
Ни один из основных используемых компиляторов на не8-битках при линковании исполняемого файла со статическими библиотеками не тянет все поголовно ф-ции, если они не используются. Не надо проецировать Борландовские поделия на все остальные компиляторы.Врушки. Ещё - Microsoft Quick C, DJGPP для Windows, Tiny C (tcc) (http://bellard.org/tcc/) и почти все старые сишные компиляторы, с которыми я работал. Должным образом эта проблема, пожалуй, решена только в GCC (дополнительными ключами командной строки: -ffunction-sections, -fdata-section, --gc-sections) и в MS Visual C++.
Как ведет себя в этом случае сдцц я не в курсе, но подозреваю что такой примитивный вариант оптимизации там осилили.Нет. Я реквестил его, но Филлипа это не пробрало. ;) Видимо, он делает библиотеки также как Sergey и не считает эту задачу насущной. Ещё я пробовал пробить данную возможность в сообщество разработчиков tcc (http://lists.nongnu.org/archive/html/tinycc-devel/2012-10/msg00000.html), но и там отнеслись прохладно. Проще говоря, отказали. Почитайте, чем аргументировали.
Так что в XDev использование утилиты smartlib - не роскошь, а злободневная потребность. Особенно с учётом того, что некоторые компиляторы уже никогда не доработают (например, Turbo C).
Если не осилили то здравый вариант разбивать на модули с ф-циями объединенными по некоему признаку. В этом случае из статической библиотеки слинкуются только те объектники, которые содержат используемые ф-ции.С тем, что связанные друг с другом рекурсивно функции или переменные, которые используются только совместно с некоторой функцией можно пускать одним куском, никто и не спорит.
Вопрос в том, как именно поступить: разделить исходник библиотеки по "ф-циями объединенными по некоему признаку" на несколько кусков вручную, т.е. каждый такой кусок держать в виде отдельного файла, собирать мейком и радоваться. Либо же, как предлагаю я, иметь всю библиотеку в виде одного исходника и бить её на куски автоматически (места разделения кусков указываются программистом также вручную) в процессе сборки библиотеки. Как по мне, второй вариант значительно удобнее. Говорю как человек, сделавший большое количество библиотек для SDCC. За счёт того, что всё в рамках одного файла - проще редактировать, искать, переносить. Плюс с разделителями смотрится красиво.
Врушки. Ещё - Microsoft Quick C, DJGPP для Windows, Tiny C (tcc) и почти все старые сишные компиляторы, с которыми я работал. Должным образом эта проблема, пожалуй, решена только в GCC (дополнительными ключами командной строки: -ffunction-sections, -fdata-section, --gc-sections) и в MS Visual C++.
Ну конечно. Если целенаправленно брать для сравнения ***** мамонта, не оборудованное требуемой фичей, то получится очень убедительный рассказ про "добрую половину компиляторов". Про icc,code warrior,watcom,clang,etc не говоря уже про С++ компиляторы, говорить и учитывать при этом не стоит- чтоб статистику не портить наверное.
И да, djgpp какбэ базирутся на gcc- так что определись, есть в нем оптимизация или нет.
NovaStorm
10.06.2014, 08:42
>gcc
>есть в нем оптимизация или нет
LTO до сих пор скорее нет, чем есть.
LTO до сих пор скорее нет, чем есть.
На работу связки data-section/function-section/gc-sections это как-то влияет?
Q-Master
10.06.2014, 21:12
Вопрос в том, как именно поступить: разделить исходник библиотеки по "ф-циями объединенными по некоему признаку" на несколько кусков вручную, т.е. каждый такой кусок держать в виде отдельного файла, собирать мейком и радоваться. Либо же, как предлагаю я, иметь всю библиотеку в виде одного исходника и бить её на куски автоматически (места разделения кусков указываются программистом также вручную) в процессе сборки библиотеки. Как по мне, второй вариант значительно удобнее. Говорю как человек, сделавший большое количество библиотек для SDCC. За счёт того, что всё в рамках одного файла - проще редактировать, искать, переносить. Плюс с разделителями смотрится красиво.
Первый вариант аутентичен для любого проекта на С/С++. В принципе он вполне аутентичен для ассемблерного кода. Исходя из этого (ну и из того что аутентичным его сделали нифига не глупые люди) это оптимальный вариант с не очень большим оверхедом.
Второй вариант во-1 очень трудно поддерживаем, т.к. требует не статической либы с кучей скомпилированных .o файлов внутри, а какого-то адского гемороя по указыванию какие куски откуда надо выкусить и куда собрать ( с этим вполне справляется компилятор без необходимости в программисте). Во-2, такой вариант нечитаем. В-3, сборка проекта будет увеличена ровно на время разбиения мегасорца на куски и последущей компиляции этой помойки. В-4, ошибки при таком разбиении практически гарантированы и вызывают п.3 в полный рост КАЖДЫЙ раз.
Могу предложить еще 3й вариант как компромисс между 1м и 2м:
config.h с куче #define где указывается какие ф-ции надо компилировать из исходников, а какие нет. Вариант имеет часть недостатков 2го метода, ибо требует пересборки при каждом изменении в количестве используемых ф-ций.
PS: Не понимаю я в чем проблема сделать выкидывание мертвого кода из собираемого файла в компиляторе...
PPS: Не думаю что выучить make или cmake это дичайшая из проблем.
Oleg N. Cher
10.06.2014, 22:19
Про icc,code warrior,watcom,clang,etc не говоря уже про С++ компиляторы, говорить и учитывать при этом не стоит- чтоб статистику не портить наверное.Наверное ты не заметил, что я говорил про старые компиляторы вообще, и про те, с которыми я работал, в частности. Перечитай пост, если от тебя это какбэ ускользнуло.
И да, djgpp какбэ базирутся на gcc- так что определись, есть в нем оптимизация или нет.А ещё ты наверно не обратил внимание, что я говорил про DJGPP для Windows, и я не знаю, слышал ли ты вообще про такую доработку данного компилятора от Макса Феоктистова (http://smallsrv.com/mkpe/). Я говорил не про DJGPP для DOS32, и мы можем очень продуктивно обсудить данный вопрос, только ты в этой специфической области будешь какбэ некомпетентен. Уточню, речь идёт про наличие возможности пихать в статическую библиотеку код с одного сишного файла-исходника таким образом, чтобы при линковке из библиотеки брались только используемые сущности.
На работу связки data-section/function-section/gc-sections это как-то влияет?Линкер Макса Феоктистова не поддерживает gc-sections.
AOT: SDCC не оборудован обсуждаемой фичей, посему остаётся бить исходник на куски. Если кто-то пролоббирует, а разрабы SDCC реализуют, выкинем нафик smartlib и будем только рады.
А ещё хочу заметить, что сейчас занят внедрением сматрлинковки в библиотеку Laser, и там уже получается > 120 кусков. И я бы чокнулся, если бы пришлось редактировать и переносить куски кода между 120 файлами. Это факт.
P.S. Вот меня умиляет дикое количество здешних воинствующих сишников, не сделавших/адаптировавших ни одной библиотеки для Спека. ;) А если я неправ, то ГДЕ ССЫЛКИ НА ЭТИ БИБЛИОТЕКИ?
---------- Post added at 21:19 ---------- Previous post was at 21:10 ----------
Второй вариант во-1 очень трудно поддерживаем, т.к. требует не статической либы с кучей скомпилированных .o файлов внутри, а какого-то адского гемороя по указыванию какие куски откуда надо выкусить и куда собрать ( с этим вполне справляется компилятор без необходимости в программисте).Всем этим "аццким гемороем" занимается одна-единственная утилита smartlib и делает всё автоматически. Программисту остаётся только указать "линии разреза" между функциями, помещаемыми в библиотеку отдельно.
Притом она, эта утилита, очень полезна не только для SDCC, но и для tcc, DJGPP для Windows и т.д. Кстати, по методу Макса Феоктистова можно собирать сверхмаленькие EXE и DLL размером от 1 кб. Т.е. они в принципе получаются небольшими, без специальных ухищрений.
Во-2, такой вариант нечитаем.Во-2, вы лично не адаптировали ни одной библиотеки для SDCC и рассуждаете чисто теоретически? ;)
В-3, сборка проекта будет увеличена ровно на время разбиения мегасорца на куски и последущей компиляции этой помойки.Называю нехорошим словом то, что мне не нравится, да? ;)
К слову, да, собирает дольше. Ну а как иначе. Но дольше не из-за разбивки, она происходит мгновенно. Дольше из-за того, что каждый кусок при сборке тянет свои хидеры, компилятору их надо заново парсить, это требует времени, в т.ч. и в случае варианта 1 от Sergey.
В-4, ошибки при таком разбиении практически гарантированы и вызывают п.3 в полный рост КАЖДЫЙ раз.Да чушь вы говорите. Разрабатываю библиотеки уже годами, ноль проблем. А вот пока не изобрёл такой способ - здесь некоторые товарищи бухтели про то, что "этот долбанный SDCC ещё и всё из библиотек тянет, оказывается, ай-яй-яй какой он нехороший".
Могу предложить еще 3й вариант как компромисс между 1м и 2м:
config.h с куче #define где указывается какие ф-ции надо компилировать из исходников, а какие нет. Вариант имеет часть недостатков 2го метода, ибо требует пересборки при каждом изменении в количестве используемых ф-ций.Поясните.
PS: Не понимаю я в чем проблема сделать выкидывание мертвого кода из собираемого файла в компиляторе...Ну да, проблем вроде быть не должно, но работаем ведь с готовыми компиляторами и не всегда есть возможность повлиять на направление их развития. А вы почитали, чем аргументируют отказ внедрения этой фичи разработчики tcc? Удивительное дело, оказывается здесь всё не так однозначно, как я думал...
Alcoholics Anonymous
11.06.2014, 00:08
> Да чушь вы говорите. Разрабатываю библиотеки уже годами, ноль проблем. А вот пока не изобрёл такой способ - здесь некоторые товарищи бухтели про то, что "этот долбанный SDCC ещё и всё из библиотек тянет, оказывается, ай-яй-яй какой он нехороший".
Основная проблема заключается в люди не знают, как писать библиотеки. Они используются для популярных монтажников на спектр, которые "маленькая машинка мышление" и не имеют связей возможности.
Последовательную компоновку, безусловно, является особенностью sdasz80 и о нескольких других Z80 монтажников, как z80asm в z88dk и сборщиком в Binutils. Эти сборщики только приложить код из библиотек, которые действительно используются в программе. В z88dk мы зависим от него, потому что у нас есть более чем 64К кода и данных в библиотеке спектра, например, и если последовательную компоновку не работал, даже такой программы, как "основной () {}" будет сильному нажиму, чтобы соответствовать в 64k :)
Та часть, которая ловит людей в том, что все связующие работать в единицах модулей, что соответствует отдельных файлов. Библиотека код должен быть разбит на самых маленьких функций, которые имеют смысл и те отдельные функции должны быть, содержащихся в их собственных файлов. У нас есть более 5000 в z88dk и хотя вы говорите, было бы сойти с ума, чтобы сделать это, это на самом деле лучший способ делать вещи. Одна вещь, вы найдете, как ваши библиотеки ASM расти в том, что объем памяти является проблемой. Вы хотите, чтобы ваш код библиотеки для повторного использования столько кода, сколько возможно. Вы же не хотите, например, пять различных умножения процедуры, потому что пять различных библиотеки встроены собственную умножения. Эти крошечные подпрограммы должны быть доступны как правило, и используется все, чтобы снизить конечную размер бинарного кода, и это достигается только, когда вы пишете библиотеки разбитые на мелкие кусочки. Головная боль вы получили от создания библиотеки Лазерная Basic в основном потому, что вы должны были развалится чужой монолитный каплю, и это не приятная задача, ни интересным. Но если вы пишете с нуля, это очень простой и хороший способ организовать исходный код.
Ваш "умный связывание" идея еще один шаг вперед, но он никогда не будет получить много сцепление с не-объектно-ориентированных компиляторов просто потому, что описанный выше метод лучше для своих библиотек, поскольку позволяет максимально повторное использование кода и лучшей организации исходного кода.
Я могу говорить с этим, написав тысячи библиотечных функций, что есть только недостатки в письменной форме код библиотеки с более чем одним библиотечной функции в одном файле.
Я вижу, где вы можете сделать это для создания библиотеки с использованием языка высокого уровня. Но для императивных языков, таких как C, я все еще думаю, что это предпочтительно делать библиотеки в том же порядке, одну функцию для каждого файла. Вот пример с примитивным дискового ввода / вывода для копий в минуту: http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/fcntl/cpm/
Даже для абстрактных типов данных, которые эффективно объектов, это все еще хороший способ организовать код. Вот реализация векторного <char>:
http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/adt/b_vector/z80/
Как это обычно бывает в C, обзорный делается с помощью искажение имени. "Asm_" показывает, что функция непосредственно вызывается из собраний, "b_vector_" делает все эти функции "методы" вектора "объекта" байт. Все "методы объекта" находятся в одной директории, так же, как все функции, реализующие + + объект C, как правило, быть в одном файле.
Я думаю, что это лучший способ организовать код так. Конечно положить все эти функции в один файл и имеющие компилятора раскол его на части не имеет никаких преимуществ вообще и намного хуже с организационной точки зрения.
Я думаю, что "умный связывание" начинает иметь смысл, когда вы начинаете смотреть на объектно-ориентированных языках. Тогда имеет организационную смысл иметь все функции, реализующие объект в одном файле. Тогда вы хотите, чтобы компилятор пойти туда и забрать его на части для компоновщика, чтобы каждый метод объекта индивидуально связаны против. Способ сделать это, чтобы иметь компилятор соответствующим калечить имена, чтобы обзорного правила еще можно повиновался, когда отдельные методы объекта сделаны глобальные для компоновщика.
== english ===
The main problem is people do not know how to write libraries. They are used to the popular assemblers on the spectrum which are "small machine thinking" and do not have linking capability.
Incremental linking is certainly a feature of sdasz80 and of a few other z80 assemblers like z80asm in z88dk and the assembler in binutils. These assemblers will only attach code from the libraries that are actually used in the program. In z88dk we depend on it because we have more than 64k of code and data in the spectrum library, for instance, and if incremental linking did not work, even a program like "main(){}" would be hard-pressed to fit in 64k :)
The part that catches people is that all linkers work in units of modules, which corresponds to individual files. Library code must be broken into the smallest functions that make sense and those individual functions must be contained in their own files. We have over 5000 in z88dk and although you're saying it would drive you nuts to do that, it's actually the best way to do things. One thing you'll find as your asm libraries grow is that memory space is a problem. You want your library code to reuse as much code as possible. You do not want, for example, five different multiply routines because five different libraries inlined their own multiply. These tiny subroutines must be made available generally and used by everything to reduce the final binary size, and this is only achieved when you write libraries broken into small pieces. The headache you got from creating a Laser Basic library is mainly because you had to break apart someone else's monolithic blob and that's not a pleasant task nor an interesting one. But if you write from scratch it's a very simple and good way to organize source code.
Your "smart linking" idea is going one step further but it will never gain much traction with non-object-oriented compilers simply because the method described above is better for their libraries as it enables maximum code reuse and better organization of source code.
I can speak to that, having written thousands of library functions, that there are only disadvantages in writing library code with more than one library function per file.
I can see where you may want to do this for making libraries using a high level language. But for imperative languages like C, I still think it is preferable to make the libraries in the same manner, one function per file. Here's an example with primitive disk i/o for cpm: http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/fcntl/cpm/
Even for abstract data types, which are effectively objects, it's still a good way to organize code. Here's an implementation of a vector<char>:
http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/adt/b_vector/z80/
As is typical in C, scoping is done using name mangling. "asm_" indicates the function is directly called from assembly, "b_vector_" makes all these functions "methods" of the byte vector "object". All "object methods" are in one directory, just as all functions implementing a C++ object would typically be in one file.
I think that's the best way to organize code like that. Certainly putting all those functions into one file and having the compiler split it apart has no advantage at all and is much worse from an organizational point of view.
I think "smart linking" begins to make sense when you start looking at object oriented languages. Then it makes organizational sense to have all the functions implementing an object in one file. Then you want the compiler to go in there and pick it apart for the linker so that each object method is individually linked against. The way to do this is to have the compiler suitably mangle the names so that scoping rules can still be obeyed when individual object methods are made global for the linker.
. Дольше из-за того, что каждый кусок при сборке тянет свои хидеры, компилятору их надо заново парсить, это требует времени, в т.ч. и в случае варианта 1 от Sergey.
У асма, кстати, есть такая функция объявлять неизвестные имена глобальными. И этот ключик ему можно передать из sdcc.
sdcc -mz80 -c -Wa -g filename.c
После этого, вроде как, не обязательно каждой функции хедер давать. Все либы так собираю, - вроде, полёт нормальный.
Oleg N. Cher
11.06.2014, 02:10
Sergey, спасибо. Это и правда может ускорить сборку библиотек. Будем экспериментировать.
Dear Alcoholics Anonymous,
In many ways you are right, and in many ways I agree with you. The difference between the two approaches is only in conceptual terms of thinking. So I think:
Many functions = One module = One source file (.h and .c) => One library
And you think:
One function = One module = One source file
Many functions = Many modules = Many source files => One library
I affirm in the dispute with Q-Master, that the first approach is more typical for Pascal/Oberon-world, and the second is typical for C-world.
So our discussion around this topic will be a dispute over paradigms and approaches: what assume a module? what assume a library? In general, I'm also against the spliting a C-source to pieces, but while SDCC has not support the feature, I need to have Pascal/Oberon point of view to this problem.
Also I see no obstacles to develop object-oriented libraries for XDev in Oberon-2 (with help of "smartlib" too, of course).
Наверное ты не заметил, что я говорил про старые компиляторы вообще, и про те, с которыми я работал, в частности. Перечитай пост, если от тебя это какбэ ускользнуло.
Ну а Q-Master говорил про основные используемые компиляторы (сиречь, более-менее современные). Перечитай пост, если от тебя это какбэ ускользнуло.
А ещё ты наверно не обратил внимание, что я говорил про DJGPP для Windows, и я не знаю, слышал ли ты вообще про такую доработку данного компилятора от Макса Феоктистова. Я говорил не про DJGPP для DOS32, и мы можем очень продуктивно обсудить данный вопрос, только ты в этой специфической области будешь какбэ некомпетентен. Уточню, речь идёт про наличие возможности пихать в статическую библиотеку код с одного сишного файла-исходника таким образом, чтобы при линковке из библиотеки брались только используемые сущности.
Я использовал djgpp для винды. ЕМНИП, оригинальный. В чем суть доработки?
P.S. Вот меня умиляет дикое количество здешних воинствующих сишников, не сделавших/адаптировавших ни одной библиотеки для Спека. А если я неправ, то ГДЕ ССЫЛКИ НА ЭТИ БИБЛИОТЕКИ?
Я делал библиотеки для спека на ассемблере.
Делал библиотеки для встроенных систем на С.
Делал библиотеки для довольно широкого спектра оборудования на С++.
Я воинствующий сишник?
Oleg N. Cher
11.06.2014, 12:42
Ну а Q-Master говорил про основные используемые компиляторы (сиречь, более-менее современные).А зачем в контексте обозначения части компиляторов, в которых эта проблема не решена, говорить про компиляторы, где она решается? Я какбэ не настаиваю на использовании утилиты smartlib во всех случаях, но только там, где это будет уместно.
Я использовал djgpp для винды. ЕМНИП, оригинальный. В чем суть доработки?Не знаю никакого DJGPP для винды, кроме MINGW. Ну и кроме патча Макса Феоктистова. Суть доработки в том, что оно - изначальное для DOS32 - заточено для генерации Win32 PE.
Я воинствующий сишник?Не знаю куда ты себя относишь, но мне лично бы хотелось чтобы люди вибрировали на частоте конструктивности и творчества, а не придирались к формулировкам, отстаивая собственную важность, даже если эти формулировки не очень точные.
Нас с Сергеем смущает, что нас идут учить делать библиотеки люди, которые ни одной не сделали (имеются ввиду библиотеки для SDCC + ZX). Причём аргументируют тем, что какбэ, скорее всего, эта оптимизация в SDCC есть, они так думают - ну не может её не быть. Что грустно, потому что вопрос мною обнажён предельно, ибо обсуждался с Филиппом Краузе лично (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=32&hilit=Philipp).
Поскольку здесь нет уточнения, то подразумеваются ВСЕ компиляторы, вне зависимости от года выпуска и целевой платформы. А это весьма снижает правдивость заявления, на что и указал Q-Master, не забыв привести критерий для рассматриваемого им круга компиляторов.Цитирую.
Ни один из основных используемых компиляторов на не8-битках при линковании исполняемого файла со статическими библиотеками не тянет все поголовно ф-ции, если они не используются. Не надо проецировать Борландовские поделия на все остальные компиляторы.Поясняю. Человек даже не совсем понимает специфику разговора, поскольку обсуждается возможность умной линковки библиотеки с одного исходника, а библиотеки в упомянутых им компиляторах построены на модулях из кусочков: одна функция = один исходник.
Там я упоминал, что имею ввиду только добрую половину тех старых компиляторов, с которыми работал. И сюда не входят ни clang, ни Watcom. А откуда я могу знать, как дела обстоят там, если не видел.
И перед тем, как продолжать флейм, надо определиться: мы будем дальше говорить за все компиляторы вперемешку, или только про перечисленные мной? И про "одна функция = один исходник (с возможностью умной линковки)" или про "один исходник = одна библиотека (с возможностью умной линковки)".
А зачем в контексте обозначения части компиляторов, в которых эта проблема не решена, говорить про компиляторы, где она решается? Я какбэ не настаиваю на использовании утилиты smartlib во всех случаях, но только там, где это будет уместно.
В том и суть, что контекст не был обозначен ("все компиляторы"- слишком широко). Отсюда и весь сыр-бор.
Не знаю никакого DJGPP для винды, кроме MINGW. Ну и кроме патча Макса Феоктистова. Суть доработки в том, что оно - изначальное для DOS32 - заточено для генерации Win32 PE.
Вот опять- расхождение в терминологии. Под "для винды" я понимаю запускаемость бинарников тулчейна на винде, а не целевую платформу кодогенерации. Ибо тот же mingw бывает и "для линукса".
А чем, собственно, mingw хуже пропатченного djgpp?
Нас с Сергеем смущает, что нас идут учить делать библиотеки люди, которые ни одной не сделали (имеются ввиду библиотеки для SDCC + ZX). Причём аргументируют тем, что какбэ, скорее всего, эта оптимизация в SDCC есть, они так думают - ну не может её не быть. Что грустно, потому что вопрос мною обнажён предельно, ибо обсуждался с Филиппом Краузе лично.
1) приведи примеры попыток "учить делать" (хотя бы от меня)
2) приведи цитату, где утверждается (или хотя бы предполагается), что в SDCC такая оптимизация есть
библиотеки в упомянутых им компиляторах построены на модулях из кусочков: одна функция = один исходник.
Это тебе кто сказал? Или ты исходником называешь секцию объектного файла?
Oleg N. Cher
11.06.2014, 14:14
В том и суть, что контекст не был обозначен ("все компиляторы"- слишком широко). Отсюда и весь сыр-бор.Неконструктивный сыр-бор, заметь. Он не был бы таким, если бы кто-нибудь составил список компилеров, которые соответствуют обозначенному критерию "умной линковки библиотеки с одного исходника".
Вот опять- расхождение в терминологии. Под "для винды" я понимаю запускаемость бинарников тулчейна на винде, а не целевую платформу кодогенерации.Но ты ведь не будешь отрицать, что можно говорить "для винды" и в контексте таргет-платформы?
А чем, собственно, mingw хуже пропатченного djgpp?Патч для DJGPP просто раньше появился, ещё до MINGW. А для меня он привлекателен по нескольким причинам, не касающимся данного топика.
1) приведи примеры попыток "учить делать" (хотя бы от меня)Привожу.
Второй вариант во-1 очень трудно поддерживаем, т.к. требует не статической либы с кучей скомпилированных .o файлов внутри, а какого-то адского гемороя по указыванию какие куски откуда надо выкусить и куда собрать ( с этим вполне справляется компилятор без необходимости в программисте). Во-2, такой вариант нечитаем. В-3, сборка проекта будет увеличена ровно на время разбиения мегасорца на куски и последущей компиляции этой помойки. В-4, ошибки при таком разбиении практически гарантированы и вызывают п.3 в полный рост КАЖДЫЙ раз. Могу предложить еще 3й вариант как компромисс между 1м и 2м:
config.h с куче #define где указывается какие ф-ции надо компилировать из исходников, а какие нет. Вариант имеет часть недостатков 2го метода, ибо требует пересборки при каждом изменении в количестве используемых ф-ций. ( притом так и не пояснил, наверное потому, что это вызовет такую критику, что ой, притом не только от меня. ;) )
2) приведи цитату, где утверждается (или хотя бы предполагается), что в SDCC такая оптимизация естьПривожу.
Как ведет себя в этом случае сдцц я не в курсе, но подозреваю что такой примитивный вариант оптимизации там осилили.
Это тебе кто сказал? Или ты исходником называешь секцию объектного файла?В SDCC так и есть: один исходник = секция = атомарная единица линковки. А ты прочёл сообщение от Alcoholics Anonymous и понял, какой именно способ представления библиотеки он отстаивает?
Вместо озвучивания уточнения "я имею в виду те старые компиляторы, с которыми имел дело" (снимающего все вопросы), ты продолжал лишь держать его в голове и спорить с теми, кто про данное уточнение не в курсе.Да я озвучивал, притом в нескольких сообщениях. Перечитай, раз запамятовал.
Неконструктивный сыр-бор, заметь. Он не был бы таким, если бы кто-нибудь составил список компилеров, которые соответствуют обозначенному критерию "умной линковки библиотеки с одного исходника".
Как минимум: gcc (с вышеупомянутыми опциями), msvc. Т.е. то, что ты уже перечислил. Т.е. сам себе спротиворечил.
Но ты ведь не будешь отрицать, что можно говорить "для винды" и в контексте таргет-платформы?
"Тулчейн под линукс для винды"- догадайся с одной попытки, что здесь имеется в виду.
Привожу.
А как отличить "пытался учить делать" от "делился опытом"?
А ты прочёл сообщение от Alcoholics Anonymous и понял, какой именно способ представления библиотеки он отстаивает?
Да. Одна функция=один файл. Поскольку он ссылается на свой опыт, я сделаю то же самое: разбитие по аспектам и уровням абстракции гораздо более сопровождаемее. Если писать что-то сложнее "тыщи библиотечных функций", то вскоре застрелишься от беспричинной сложности.
То, что линковщик не умеет выкидывать ненужное- это его проблема. Если вышележащее окружение умеет ее обходить (компилятор ли сам по секциям раскидывает или твоя тулза распиливает входной файл) незаметно для пользователя- все хорошо. Но если ограничения компилятора усложняют жизнь пользователя (причем настолько, что принуждает перестраивать сознание), лишают альтернатив (любитель писать каждую функцию в своем файле прекрасно будет пользоваться окружением с умным линковщиком), это категорически неправильно.
Oleg N. Cher
11.06.2014, 16:31
Как минимум: gcc (с вышеупомянутыми опциями), msvc. Т.е. то, что ты уже перечислил. Т.е. сам себе спротиворечил.И в чём же это противоречие?
А как отличить "пытался учить делать" от "делился опытом"?Делился опытом чего? Того, что мы с Сергеем уже делали, а он - нет? Кроме того, он не так и не пояснил свой способ в подробнностях. А я не вижу преимуществ в том, чтобы налепить #ifdef'ов и "выборочно компилировать" вместо "линий разреза" и smartlib.
Да. Одна функция=один файл. Поскольку он ссылается на свой опыт, я сделаю то же самое: разбитие по аспектам и уровням абстракции гораздо более сопровождаемее. Если писать что-то сложнее "тыщи библиотечных функций", то вскоре застрелишься от беспричинной сложности.Ну так а я о чём. В моём представлении модуль (или библиотека) - это группа связанных функций определённого назначения, которая может быть оснащена инициализатором и деинициализатором (в терминах ООП - конструктором и деструктором), вызов которых гарантирует корректную работу части (или вообще всех) функций модуля (библиотеки). Логическая связность функций подталкивает к связности представления и размещения их в одном исходнике. Впрочем, я не буду настаивать, делайте как удобно. Но делайте. ;)
То, что линковщик не умеет выкидывать ненужное- это его проблема.Это проблема тех, кто делает библиотеки для SDCC исходя из концепта, который ты озвучил фразой выше.
Еще раз: в том сообщении, с которого начался спор (первое в этой теме), уточнения не было.Но разве не было ясно, что я не могу знать тонкостей всех компиляторов, а говорю только про те, которые юзал?
Q-Master
11.06.2014, 16:31
Всем этим "аццким гемороем" занимается одна-единственная утилита smartlib и делает всё автоматически. Программисту остаётся только указать "линии разреза" между функциями, помещаемыми в библиотеку отдельно.
Притом она, эта утилита, очень полезна не только для SDCC, но и для tcc, DJGPP для Windows и т.д. Кстати, по методу Макса Феоктистова можно собирать сверхмаленькие EXE и DLL размером от 1 кб. Т.е. они в принципе получаются небольшими, без специальных ухищрений.
См. ниже. Утилита в целом-то не особенно и нужна.
Во-2, вы лично не адаптировали ни одной библиотеки для SDCC и рассуждаете чисто теоретически? ;)
В чем состоит "адаптирование"?
Нечитаемость заключается в том, что в 1 гигантском файле находится огромное количество функций, которые представляют из себя кашу с совершенно разным функционалом никак не разделенную. В результате понять где что находится и как работает - то еще приключение.
Я говорю это все не голословно, а исключительно с точки зрения большого опыта.
Называю нехорошим словом то, что мне не нравится, да? ;)
А как еще назвать то, во что превращается банальная компиляция 1 исходника? Реально получается мегапомойка из кучи *.c файлов с кучей ненужных инклюдов и прочего.
К слову, да, собирает дольше. Ну а как иначе. Но дольше не из-за разбивки, она происходит мгновенно. Дольше из-за того, что каждый кусок при сборке тянет свои хидеры, компилятору их надо заново парсить, это требует времени, в т.ч. и в случае варианта 1 от Sergey.
См. ниже. Проблема решается красивше, но не лучше.
Да чушь вы говорите. Разрабатываю библиотеки уже годами, ноль проблем. А вот пока не изобрёл такой способ - здесь некоторые товарищи бухтели про то, что "этот долбанный SDCC ещё и всё из библиотек тянет, оказывается, ай-яй-яй какой он нехороший".
Вы изобрели велосипед, причем с квадратными колесами и без педалей. Куда раньше велосипед изобрели писатели libtool.
Поясните.
Поясняю. Все элементарно и давно придумано в libtool. Решение простое и не требует никаких лишних "линий разреза" и утилит и решается исключительно компилятором (точнее пре-процессором).
Идея следущая:
в начале xxx.h подключается config.h в котором на каждую используемую ф-цию добавлена 1 строчка #define USE_XXXX 1 либо #undef USE_XXXX
в самом xxx.h и в xxx.c перед каждым определением и реализацией ф-ции стоит #ifdef USE_XXXX и в конце #endif. Полностью убирает проблему с резьбой мегафайла на кучу мелких и жутких тормозов компиляции. Не решает проблему гигантского сорца.
Oleg N. Cher
11.06.2014, 16:59
См. ниже. Утилита в целом-то не особенно и нужна.Вам - конечно не особенно нужна, потому что вы не делаете библиотек для SDCC.
В чем состоит "адаптирование"?В том, чтобы это собиралось и работало. И могло быть вызвано из сишного кода.
И когда мы говорим об адаптировании библиотек к SDCC, мы имеем ввиду что нам не тычут в носик асмовский исходник, а причёсывают его, переводят в синтаксис sdasz80, снабжают высокоуровневым интерфейсом, возможно, адаптируют передачу параметров, оптимизируют и, наконец, отлаживают. А если по канонам ZXDev, то ещё можно и соединить несколько сходных функций в одну с конфигуратором, за счёт чего достигается гибкость разработки. Подробнее здесь (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=94).
Нечитаемость заключается в том, что в 1 гигантском файле находится огромное количество функций, которые представляют из себя кашу с совершенно разным функционалом никак не разделенную.Во-первых я вообще нигде не предлагал пихать все функции в мире в одну библиотеку, это вы только что придумали и приписываете мне.
Во-вторых ясно, что сцеплять надо сходные функции, чтобы был цельный взгляд на библиотеку. Посмотрите внимательнее. Есть библиотека Basic, которая содержит реализацию операторов ZX-Basic. Это гигантская помойка не связанных между собой функций? Далее, Laser - функции Laser Basic, и т.д.
В-третьих ваша сентенция "никак не разделенную" никак не может быть истинной, потому что я уже много раз талдычил про "линию разреза".
В результате понять где что находится и как работает - то еще приключение.Интересный аргумент. То есть если файлов с функциями, которые даже связаны логически, большая куча, то понять где что находится и как работает - легко. Но если они вдруг в одном исходнике, то это становится большой проблемой. ;)
А как еще назвать то, во что превращается банальная компиляция 1 исходника? Реально получается мегапомойка из кучи *.c файлов с кучей ненужных инклюдов и прочего.Я как раз критикую кучу *.c файлов. А знаете чем отличается куча файлов z88dk или, например, библиотек Сергея от моих? А ничем. Только у меня они имеют другие имена:
Basic_001.c
Basic_002.c
Basic_003.c
...
И носят временный (temporary) характер, т.е. удаляются после сборки библиотеки. В случае успешной сборки юзер может даже не заметить эту "кучу файлов". В случае же мультифайловости он не просто их заметит, а сломает об них и копья, и мозг. ;)
Вы изобрели велосипед, причем с квадратными колесами и без педалей.Я вот чего не пойму. Вы критикуете "большую кучу файлов" и способ z88dk и Сергея или мой и smartlib? Если последнее, то я не хочу и не собираюсь пихать каждую функцию в отдельный файл. Это антиоберонский путь. И античеловеческий. ;)
Но, кстати, я сам связываю несколько обероновских модулей в одну библиотеку, это возможно. Притом без бубна, достаточно доброй воли и утилиты smarlib. Но и её я никому не навязываю, просто предлагаю кому нужно. Не вам, Q-Master. Я уже понял, что библиотек для SDCC вы делать не будете.
Идея следущая:
в начале xxx.h подключается config.h в котором на каждую используемую ф-цию добавлена 1 строчка #define USE_XXXX 1 либо #undef USE_XXXX
в самом xxx.h и в xxx.c перед каждым определением и реализацией ф-ции стоит #ifdef USE_XXXX и в конце #endif. Полностью убирает проблему с резьбой мегафайла на кучу мелких и жутких тормозов компиляции. Не решает проблему гигантского сорца.
Ну вот. Вы предложили "разрезание без разрезания", фактически то же самое, что и я, только более сложным способом. И потом, зачем мне вражеская libtool вместо моей крохотной smartlib, к которой Ofront я уже адаптировал. ;)
Видите ли, в чём ещё проблема, Q-Master. Я компиляю сишные исходники, сгенерированные автоматически Ofront'ом. Поэтому вариант допихивать в них потом ручками #ifdef'ы выглядит абсолютно искусственно. Но это ещё полбеды, у варианта с libtool хватает и других недостатков.
Кстати, обероновский подход не одобряет огромные модули, наоборот, поощряются мелкие. Так что ваши попытки приписать мне идею запихивания всего-чего-можно в один мегаисходник тоже идут мимо. Истина как всегда где-то посередине. ;)
Library code must be broken into the smallest functions that make sense and those individual functions must be contained in their own files
Да,я я так и делал изначально, у себя в sdcc framework.
Пример (либа для вызова FLOS функций из Си кода)
http://sourceforge.net/p/v6z80p/code/HEAD/tree/trunk/Contributions/Valen/c_programs/c_support/os_interface_for_c/
---------- Post added at 16:47 ---------- Previous post was at 16:38 ----------
Я компиляю сишные исходники, сгенерированные автоматически
"сгенерированные автоматически" - ключевое слово
Конечно нужно сгенеренный Си файл как-то нарезать на более мелкие файлы .
(а о чем спор, я так и не понял)
Alcoholics Anonymous
11.06.2014, 22:33
Совет, кажется, слияние сообщения, так что я не могу получить комнату, чтобы поставить русских в, извините: (
= english ==
So I think:
Many functions = One module = One source file (.h and .c) => One library
And you think:
One function = One module = One source file
Many functions = Many modules = Many source files => One library
It actually comes down to how the language itself works.
One source file per function is exactly what is required by assembly language and C (no surprise as C was meant to model assembly language programming) and the incremental linking method invented in the 1960s is exactly sufficient for "smart linking" C and asm programs.
A C program not destined for a library would organize related functions on a per file basis and in user programs, it's ok to have more than one function per file because presumably the user only writes functions he uses. When it comes time to make a library, it's not a big deal to take all the functions from one file and separate them into one file per function in a directory by hand. The directory acts like the class or module name, the functions in the directory are clearly visible to anyone looking for what they can do with the library and the incremental linking makes sure only what is needed is attached to the binary. The code is organized and easier to use as it's easier to see what is available.
BUT, this only works because asm and C have just two scopes -- local and global. With imperative languages like Pascal and object oriented languages, there is more than one scope. Taking Pascal as an example, a single module (? it's been a long time since I've programmed in pascal) can have many nested functions and variables in different scopes. The functions in such a module cannot be simply separated by hand into individual files for the linker -- you have to modify names to enforce scoping rules. Object oriented languages require something similar that is not easily done by hand. "Smart linking" solves this problem by automatically extracting individual functions from these nested scopes or files and breaking them into units that works for the incremental linker.
I need to have Pascal/Oberon point of view to this problem.
So I agree with you here, you need this for Pascal-like languages and oo languages. Modern day linkers still work in an incremental fashion and "smart linking" is something done by the compiler. A C compiler (like sdcc) will never need such functionality so your adding it to the toolchain as a separate utility is the right thing to do. Placing it at the C source level is a good way to do it too, and may be an occasionally useful tool for C programmers. It's how modern day compilers do it (or it was at one time), although they may not show you all the hundreds of individual files they generate and instead directly generate a library file.
Q-Master's alternative of generating a define to opt in and out of parts of the source code is another way to go that does not run into scoping issues (below). However, it only works at the source level. If you wanted to write a library in Pascal using this method and export it for use by C programmers or asm programmers, you couldn't without also exporting the source of this library in Pascal and the build environment. That's not what you want.
The difficulty with "smart linking" is it changes the scope of functions and variables. By extracting each individual function into its own file, you make that function global.
Problems in C:
static int a = 5;
static int multiply(int a, int b)
{
return a*b;
}
main()
{
return multiply(a,6);
}
If you extract that multiply() function, you're adding it to the global scope but the C code is specifically making it local. You could end up with more than one function with name "multiply" and the linker may either complain or incorrectly link the first one it finds. You've also got the issue of how you are going to properly scope the local variable "a" above.
In Pascal-derived languages the problems are even worse because you can have many nested scopes.
Usually this is solved with judicious use of name-mangling. Above, the local variable "a" would be renamed to "xyz_a" and the local function "multiply" would be similarly renamed to "xyz_multiply". The references in main to these things would also be changed. "xyz" is some identifier that uniquely identifies the translation unit those functions are found in but it cannot be something totally random as, when building a library, you want those names to be predictable if it is to be accessed by another program or the symbols are to be understood while debugging.
Doing this requires the "smart linker" to have a lot of knowledge of the language it is splitting up and it's not a trivial program to write. So although Q-Master's method is less desirable, it does avoid these scoping problems.
I prefer your method but I don't think you have solved the scoping issues? Maybe that's what everyone is talking about when they mention clang, etc. The automatic translation is not always easy to follow.
---------- Post added at 10:33 ---------- Previous post was at 09:52 ----------
Да,я я так и делал изначально, у себя в sdcc framework.
Пример (либа для вызова FLOS функций из Си кода)
http://sourceforge.net/p/v6z80p/code/HEAD/tree/trunk/Contributions/Valen/c_programs/c_support/os_interface_for_c/[COLOR="Silver"]
Yes, that is the right way to do things for C libraries and adding a "FLOS" scope to functions helps to prevent name clashes :)
For functions implemented in asm, I'd suggest a slightly different approach from what I have seen here that separates the asm implementation from the C interface.
Separating the asm implementation has a couple of advantages:
1. You can easily accommodate different C linkages. Right now sdcc only has one linkage but it's not a good one for interfacing asm code and sometime down the road there will be alternative linkages. In z88dk we have many different linkages: sdcc R->L param order, small C L->R param order, fastcall, callee. We also have two different sdcc C interfaces: one for the library using ix and one for the library using iy. The latter leads to smaller code because the library does not have to preserve the value of ix. All of these C interfaces use the same asm implementation without any overhead.
2. Your library code becomes attractive to asm programmers. The first thing many asm programmers do when they look at C libraries is turn up their noses because of the bulky C interface code. sdcc's C interface is very bulky and this discourages asm programmers from using library code. In z88dk we completely separate the asm implementation from the C interface so that is possible to build an asm library without any C overhead.
3. The C libraries have entry points for both C code and asm code. This allows easy mingling of C and asm in programs.
The last thing I would change from some of the code I've seen is to stop using ix to index parameters passed to an asm function. It's very slow and leads to large code. It is almost always better to pop passed parameters into registers before proceeding with the asm implementation.
An example of what I suggest, using an asm implementation of strcpy():
File: asm_strcpy.asm
PUBLIC asm_strcpy
asm_strcpy:
; enter : hl = char *s2 = src
; de = char *s1 = dst
;
; exit : hl = char *s1 = dst
; de = ptr to terminating NUL in s1
;
; uses : af, bc, de, hl
push de
xor a
loop:
cp (hl)
ldi
jr nz, loop
pop hl
dec de
ret
The sdcc C interface:
File: strcpy.asm
; char *strcpy(char * restrict s1, const char * restrict s2)
PUBLIC _strcpy
_strcpy:
pop af
pop de
pop hl
push hl
push de
push af
INCLUDE "string/z80/asm_strcpy.asm"
The z88dk C interface using callee linkage, just to show that the same asm code is being used:
File: strcpy_callee.asm
; char *strcpy(char * restrict s1, const char * restrict s2)
PUBLIC strcpy_callee
strcpy_callee:
pop af
pop hl
pop de
push af
INCLUDE "string/z80/asm_strcpy.asm"
The header file for the compiler:
FILE: string.h
extern char *strcpy(void *dst, void *src);
The INCLUDEs mean there is no JP or CALL overhead to the asm implementation. The same labels from the asm implementation are available so that the C interface version also has the asm interface.
Several versions of the library are built: one for asm programmers where the asm implementation is used, one for the sdcc library where the sdcc C interface is used, etc.
Notice that none of it is embedded into a C wrapper -- this is unnecessary when a function is implemented in asm. You scan skip the compiler entirely and use the assembler directly to make the library. Using a C wrapper is not entirely harmless as sometimes preamble and postamble code may be inserted by the compiler.
Oleg N. Cher
11.06.2014, 22:35
Господа, что в сухом остатке.
Споры о точности формулировок являются неконструктивными. Обсуждение не-спектрумных средств разработки является оффтопиком. Вместо этого:
Нужно пролоббировать обсуждаемую нами "умную линковку" в сообщество разработчиков SDCC и tcc. Тогда вопрос об использовании smartlib станет неактуальным как минимум в контексте разработки на SDCC.
Надо разработать и адаптировать на SDCC побольше библиотек для ZX. ;)
I prefer your method but I don't think you have solved the scoping issues?Ofront (and later, me) use name-mangling by such way:
MODULE Abc;
IMPORT Fast, Compact, Standard, MyOwn; (* Different libraries *)
CONST A=5; (* internal constant *)
B* = 10; (* external/exported constant. the C-name is Abc_B *)
PROCEDURE GetCompactMult* (): INTEGER; (* C name is Abc_GetCompactMult *)
BEGIN
RETURN Compact.Mult(A, B); (* Used compact-way *)
END GetMult;
PROCEDURE GetFastMult* (): INTEGER; (* C name is Abc_GetFastMult *)
BEGIN
RETURN Fast.Mult(A, B); (* Used fast-way *)
END GetFastMult;
END Abc. (* No conflict of names *)All the name conflict problems were solved by Josef Templ, the author of Ofront translator.
Maybe that's what everyone is talking about when they mention clang, etc. The automatic translation is not always easy to follow.You prefer C/asm coding. :) I prefer to code in Oberon and translate to C. Ofront is my assistant of this work - it translates Oberon to C automatically. And yes, C is closer to the low-level coding, and more suitable for coding for Z80 than Oberon - I know. ;)
Oleg N. Cher, технический вопрос по поводу твоей утилиты разрезания на функции.
Как обрабатываются приватные (static) функции?
Oleg N. Cher
12.06.2014, 13:41
Vitamin, сама утилита ничего особо умного не делает, но делает буквально следующее. Берёт сишный файл-исходник библиотеки со множеством функций:
#include "SYSTEM.h"
export void NewSupercode_EKRAN_1 (SHORTCARD x);
export void NewSupercode_EKRAN_2 (SHORTCARD x);
/*================================== Header ==================================*/
void NewSupercode_EKRAN_1 (SHORTCARD x) {
__asm
LD HL, #2
ADD HL, SP
LD L, (HL) // x
LD H, #0
LD DE, #0x5800
LD BC, #0x300
LDIR
__endasm;
} //NewSupercode_EKRAN_1
/*--------------------------------- Cut here ---------------------------------*/
void NewSupercode_EKRAN_2 (SHORTCARD x) {
__asm
LD HL, #2
ADD HL, SP
LD L, (HL) // x
LD H, #0
LD BC, #0x1800
LD DE, #0x4000
LDIR
__endasm;
} //NewSupercode_EKRAN_2
...и нарезает на секции по "линиям разреза", так что получаются фрагменты, состоящие из заголовка, взятого до "линии заголовка" - он будет включен в каждый фрагмент (притом какие-либо инклюды из заголовка делать вовсе необязательно, ибо даже можно сделать нужный инклюд прямо в нужном куске). Фрагмент NewSupercode_001:
#include "SYSTEM.h"
export void NewSupercode_EKRAN_1 (SHORTCARD x);
export void NewSupercode_EKRAN_2 (SHORTCARD x);
/*================================== Header ==================================*/
void NewSupercode_EKRAN_1 (SHORTCARD x) {
__asm
LD HL, #2
ADD HL, SP
LD L, (HL) // x
LD H, #0
LD DE, #0x5800
LD BC, #0x300
LDIR
__endasm;
} //NewSupercode_EKRAN_1
Фрагмент NewSupercode_002:
#include "SYSTEM.h"
export void NewSupercode_EKRAN_1 (SHORTCARD x);
export void NewSupercode_EKRAN_2 (SHORTCARD x);
/*================================== Header ==================================*/
void NewSupercode_EKRAN_2 (SHORTCARD x) {
__asm
LD HL, #2
ADD HL, SP
LD L, (HL) // x
LD H, #0
LD BC, #0x1800
LD DE, #0x4000
LDIR
__endasm;
} //NewSupercode_EKRAN_2Потом эти кусочки в цикле скармливаются компилятору и библиотекарю, который упаковывает скомпилированные сегменты-объектники .rel в библиотеку.
Сам понимаешь, что приватные (static) функции при таком способе разбиения имеет смысл пихать только в тот фрагмент, который монопольно будет вызывать приватную функцию, потому что если выделить static-функцию в отдельный фрагмент - её извне не будет видно. Хотя никто и не запрещает.
Также я научил Ofront добавлять в генерируемый им сишный исходник те же линии заголовка и разреза, но решены отнюдь не все проблемы с автоматическим разделением, поэтому его можно использовать только в простых случаях (без static и без ООП), но поймите меня правильно: это излечимо, просто нужно придумать как доработать. Подчёркиваю: последний абзац касается только Ofront'а, которым вы всё равно не пользуетесь (и не собираетесь). Поэтому я дорабатываю его исключительно для себя. С SDCC же весь процесс регулируется ручками, так больше свободы.
Сам понимаешь, что приватные (static) функции при таком способе разбиения имеет смысл пихать только в тот фрагмент, который монопольно будет вызывать приватную функцию, потому что если выделить static-функцию в отдельный фрагмент - её извне не будет видно. Хотя никто и не запрещает.
В том и прикол, что эти приватные функции, зачастую, нужны более чем одной функции. А значит придется либо выставлять наружу то, что там не нужно, либо потерять в оптимизации (дублировать эту приватную функцию у всех пользователей, либо резать не по функциям, а по группам функций.
Плюс необходимость ручной работы по разметке- не фонтан (я думал, там более продвинутая автоматика)...
В общем, разработчику компилятора еще есть над чем работать. Как минимум, можно предоставлять информацию о связанности функций для автоматизации нарезки.
Q-Master
12.06.2014, 15:41
Ну вот. Вы предложили "разрезание без разрезания", фактически то же самое, что и я, только более сложным способом. И потом, зачем мне вражеская libtool вместо моей крохотной smartlib, к которой Ofront я уже адаптировал. ;)
Специально повторяюсь, поскольку заметил что Вы просто НЕ ЧИТАЕТЕ то что я пишу. Я сказал КАК в libtool, но не сказал что надо использовать libtool.
И мой (точнее стандартный) способ лишен тех проблем про которые говорит Витамин.
Более того, такой способ полностью убирает необходимость чего-либо куда-либо резать и компиляция происходит значительно оптимальнее. Если есть желание, то я могу написать утилиту, которая Вашу нарезку переводит в #ifdef #endif.
Видите ли, в чём ещё проблема, Q-Master. Я компиляю сишные исходники, сгенерированные автоматически Ofront'ом. Поэтому вариант допихивать в них потом ручками #ifdef'ы выглядит абсолютно искусственно. Но это ещё полбеды, у варианта с libtool хватает и других недостатков.
Думаю что доработать Ofront проблем вообще никаких нет.
Кстати, обероновский подход не одобряет огромные модули, наоборот, поощряются мелкие. Так что ваши попытки приписать мне идею запихивания всего-чего-можно в один мегаисходник тоже идут мимо. Истина как всегда где-то посередине. ;)
Тогда я не понимаю проблемы с линковкой вообще. Ее просто нет. Более того, изначальный вопрос о вариантах после Ваших-же слов становится как-то бессмысленен. Если Вас все устраивает и Вы полностью отвергаете все предложения, то какой смысл был вообще что-то спрашивать?
PS: Я за свою жизнь понаписал столько всего и на стольких языках, что говорю, обычно, не "для галочки".
Oleg N. Cher
12.06.2014, 16:34
В том и прикол, что эти приватные функции, зачастую, нужны более чем одной функции. А значит придется либо выставлять наружу то, что там не нужно, либо потерять в оптимизацииЯ за выставление её наружу, заманглировав предварительно имя таким образом, чтобы не было возможности вызвать её из Оберона (а для Си - снабдить её префиксом "__"). Ну и в Оберон-интерфейсе она мелькать не будет.
Плюс необходимость ручной работы по разметке- не фонтан (я думал, там более продвинутая автоматика)...Я не против автоматизации и доработки утилиты, мне не нравится критика тех, кому это не нужно и кто не собирается ничего дорабатывать, лишь учит нас жизни с умудрённым видом.
В общем, разработчику компилятора еще есть над чем работать. Как минимум, можно предоставлять информацию о связанности функций для автоматизации нарезки.Если сделать всё внутри SDCC, то никакой информации не будет нужно. Фрагменты нарезания будут самые атомарные. Браться будут по требованию. Лишнего не будет взято.
И мой (точнее стандартный) способ лишен тех проблем про которые говорит Витамин.А в чём преимущество прогонять целый исходник столько раз, сколько там функций? Вы ведь никак не решаете проблему инклюдов, только предлагаете засорять исходник #ifdef'ами, усложняя его и портя стиль разработки. И как вы предлагаете решать проблему локальных (static) функций, про которую говорит Витамин?
Более того, такой способ полностью убирает необходимость чего-либо куда-либо резать и компиляция происходит значительно оптимальнее.Т.е. прогон исходника в 100 кб, скажем, 100 раз вы называете более оптимальным, чем прогон 100 раз однокилобайтных кусочков нарезки? Мдя, по-моему у нас разговор ушёл вообще какие-то абстрактные области, не подхлёстываемый ничем, кроме пипискомера. Мне жаль это констатировать. Я не вижу преимущества в предлагаемом вами способе. Более того, переход на него в моём случае связан ещё и с накладными расходами по переходу. Смысл?
Думаю что доработать Ofront проблем вообще никаких нет.Нет. Вот поговорить об этом - проблем никаких нет. А доработать - это вообще мало кому под силу. А я нахожу там массу нерешённых проблем, поэтому делаю пошагово после того как полностью понята стадия следующего шага. Сейчас автоматизации разбивки можно подвергать не-ООП библиотеки без локальных функций. Дальше буду двигаться по мере необходимости.
Я вообще сейчас знаете как делаю? Транслирую Ofront'ом, но всю Си-библиотеку веду ручками и ручками в неё переношу оттранслированные куски. Пока объёмы работы небольшие - такой вариант приемлем.
Тогда я не понимаю проблемы с линковкой вообще. Ее просто нет. Более того, изначальный вопрос о вариантах после Ваших-же слов становится как-то бессмысленен.Ну как это проблемы просто нет? Ещё как есть проблема. Об этом прочитайте постами выше. Проблема в SDCC, который пихает весь исходник библиотеки без возможности смартлинковки, одним сегментом. Приходится делать библиотеку в виде кучи маленьких файлов. Вот проблема. Это не проблема только для тех, кто делает всё кусочками и вводит это в ранг религии. Но есть противоположная религия цельности. ;)
И конечно решать данную проблему никто в здравом уме в этой теме не пойдёт, зачем, вдруг юродивый Oleg N. Cher когда-нить этим займётся, а мы подождём, куда нам спешить, и потом попользуемся плодами. ;) Ведь давить инакомыслящих - гораздо более интересное занятие. ;)
В том и прикол, что эти приватные функции, зачастую, нужны более чем одной функции.Vitamin, а как решить проблему двух зайцев: a) и чтобы static функция сидела в библиотеке отдельным куском; b) и чтобы вызывать её из других функций по её имени; c) и чтобы её нельзя было вызывать из некоторых более других функций по её имени, т.е. чтобы наружу это имя не светилось.
Мне нравится сама постановка задачи! ;) Но средствами XDev (Oberon-Ofront-smartlib) она решаема автоматическим манглированием Си-имён. Т.е. из модуля Abc, написанного на Си, вызываются нелокальные конечно, но все функции модуля Abc. А вот из Оберон-модуля Cde нельзя вызвать static-функции модуля Abc, которые не экспортированы в интерфейс модуля.
Как минимум, можно предоставлять информацию о связанности функций для автоматизации нарезки.Я думаю, после приведённого мною примера NewSupercode уже понятно как можно решать эту задачу средствами smartlib.
У асма, кстати, есть такая функция объявлять неизвестные имена глобальными. И этот ключик ему можно передать из sdcc.
sdcc -mz80 -c -Wa -g filename.c
После этого, вроде как, не обязательно каждой функции хедер давать. Все либы так собираю, - вроде, полёт нормальный.
К сожалению, оказался не прав: фокус не сработает, если в функциях используются "самодельные" типы данных, которые без хедера компилятор не распознает и выдаст ошибку синтаксиса. Не сталкивался с этим, потому что меня умиляет писать типы полностью, например, "unsigned char", а не заменять на свои типа "u8".
Q-Master
13.06.2014, 15:48
А в чём преимущество прогонять целый исходник столько раз, сколько там функций? Вы ведь никак не решаете проблему инклюдов, только предлагаете засорять исходник #ifdef'ами, усложняя его и портя стиль разработки. И как вы предлагаете решать проблему локальных (static) функций, про которую говорит Витамин?
Для тех кто очень крут, но не знает что есть компиляция в С и пре-процессор я скажу. Прогон будет не 100 раз, а ровно 1 раз на 1 инклюд хедера и 1 раз при компиляции самого файла, что есть быстрее чем компиляция 100 файлов примерно в 100 раз. Выполняться будет препроцессором компилятора в памяти и происходить мегабыстро без создания кучи временных файлов, которые потом будет проблематично пере-использовать, т.к. имена генерируются автоматически и расчитывать на них нельзя. Заголовочный файл в данном случае будет 1(2-3-10 неважно) и так-же при пре-процессинге из него будет выкидываться все ненужное.
Проблема, которую описал Витамин решается автоматически в виду исключения какой-либо резьбы по дереву и объявления ф-ций там где надо. Более того такие статические ф-ции могут быть обернуты в комплексные ifdef'ы и подключаться ТОЛЬКО в случае надобности, что опять-же очень ускорит компиляцию.
Т.е. прогон исходника в 100 кб, скажем, 100 раз вы называете более оптимальным, чем прогон 100 раз однокилобайтных кусочков нарезки? Мдя, по-моему у нас разговор ушёл вообще какие-то абстрактные области, не подхлёстываемый ничем, кроме пипискомера. Мне жаль это констатировать. Я не вижу преимущества в предлагаемом вами способе. Более того, переход на него в моём случае связан ещё и с накладными расходами по переходу. Смысл?
В твоем (задолбало писать Вашем) случае 100 кб кусок кода будет по моему методу прогнан 1 раз ровно и скомпилирован в 1 .о файл который будет 1 раз прилинкован к собираемому приложению. По твоему методу это будет:
прогон 100кб файла нарезателем и сохранение 100 кусков по килобайту (в реальности с учетом хэдеров и статических ф-ций будет не по килобайту, а по полтора-два). Потом 100 компиляций в 100 объектных файлов и 100 линковок. Соотвтетственно в случае ошибки в моем случае 1 компиляция, в твоем от 1 до 100.
Преимущество очевидно и не требует переноса (в случае смены компилятора или платформы для компиляции) утилиты по нарезке и лечения ее багов буде такие найдутся.
Ну как это проблемы просто нет? Ещё как есть проблема. Об этом прочитайте постами выше. Проблема в SDCC, который пихает весь исходник библиотеки без возможности смартлинковки, одним сегментом. Приходится делать библиотеку в виде кучи маленьких файлов. Вот проблема. Это не проблема только для тех, кто делает всё кусочками и вводит это в ранг религии. Но есть противоположная религия цельности. ;)
Я уже сказал что это не проблема sdcc, а проблема исключительно придуманная и тщательно лелеемая. Пре-процессор полностью решает ее без использования сторонних утилит.
---------- Post added at 15:48 ---------- Previous post was at 15:47 ----------
Таки нужна. Может для других Си-систем, нет, а д
Таки не нужна, если пользоваться ВСЕМИ возможностями компиляторов С.
по моему методу прогнан 1 раз ровно и скомпилирован в 1 .о файл который будет 1 раз прилинкован к собираемому приложению.
Я правильно понимаю, что это будет каждый раз, при сборке приложения, которое использует библиотеку?
прогон 100кб файла нарезателем и сохранение 100 кусков по килобайту (в реальности с учетом хэдеров и статических ф-ций будет не по килобайту, а по полтора-два). Потом 100 компиляций в 100 объектных файлов
А это только при компиляции библиотеки? То есть при использовании библиотеки, происходит 100 линковок и только.
---------- Post added at 18:10 ---------- Previous post was at 18:03 ----------
Если да, то получается у Q-Master велосипед с квадратными колёсами, у Oleg N. Cher с треугольными. А правильный велосипед, это нормальный линковщик, который режет умно объектные файлы. :)
В твоем (задолбало писать Вашем) случае 100 кб кусок кода будет по моему методу прогнан 1 раз ровно и скомпилирован в 1 .о файл который будет 1 раз прилинкован к собираемому приложению. По твоему методу это будет:
прогон 100кб файла нарезателем и сохранение 100 кусков по килобайту (в реальности с учетом хэдеров и статических ф-ций будет не по килобайту, а по полтора-два). Потом 100 компиляций в 100 объектных файлов и 100 линковок. Соотвтетственно в случае ошибки в моем случае 1 компиляция, в твоем от 1 до 100.
Эта монструозная времязатратная операция нужна только ОДИН(!) раз при создании библиотеки. Далее, при компиляции целевого файла, использующего эту библиотеку, линкер будет выдёргивать из неё только те функции, которые задействованы. Неужели ты предлагаешь библиотеку собирать каждый раз при пересборке проекта?! :)
Наверное, надо внести ясность, под библиотекой в беседе, из которой выросла эта тема, понимается не Си-файл, а архив объектников, созданный библиотечным менеджером.
Преимущество очевидно и не требует переноса (в случае смены компилятора или платформы для компиляции) утилиты по нарезке и лечения ее багов буде такие найдутся.
К случаю SDCC это преимущество неприменимо. Переносить проекты с ZX-Spectrum/ZX-Evolution на другие платформы никто не собирается.
Я уже сказал что это не проблема sdcc, а проблема исключительно придуманная и тщательно лелеемая. Пре-процессор полностью решает ее без использования сторонних утилит.
Я очень критично отношусь к своим знаниям и способностям в программировании, особенно, что касается Си, и допускаю, что я тупой и несведущий, поэтому прошу дать алгоритм, как при использовании пакета SDCC сделать библиотеку (архив объектников типа "name.lib") так, чтобы при использовании её в проекте при линковке конечного файла из неё в код программы добавлялись только задействованные процедуры.
Таки не нужна, если пользоваться ВСЕМИ возможностями компиляторов С.
Если пользоваться всеми возможностями компилятора SDCC, то, конечно, резалка не нужна, потому что всё можно сделать вручную, изначально пиша (:)) каждую функцию в отдельный исходник. Но я не собираюсь тратить на это время. Если есть готовый исходник с кучей функций, я его порежу и соберу в архив объектников автоматически.
У меня такое чувство, что меня пытаются убедить, что мне неудобно то, чем я пользуюсь :)
как при использовании пакета SDCC сделать библиотеку (архив объектников типа "name.lib") так, чтобы при использовании её в проекте при линковке конечного файла из неё в код программы добавлялись только задействованные процедуры
1. У тебя есть несколько .c файлов, в каждом файле - одна Си функция.
(т.е. ты нарезал на куски свой большей исходный файл или же изначально делал "много файлов")
2. Компилишь каждый .c файл в .rel файл
(используешь sdcc ключик "-c", который значит: только компилить и не линковать)
3. с помощью sdcclib, добавляешь .rel файлы, в один .lib файл
(по памяти написал)
1. У тебя есть несколько .c файлов, в каждом файле - одна Си функция.
(т.е. ты нарезал на куски свой большей исходный файл или же изначально делал "много файлов")
2. Компилишь каждый .c файл в .rel файл
(используешь sdcc ключик "-c", который значит: только компилить и не линковать)
3. с помощью sdcclib, добавляешь .rel файлы, в один .lib файл
(по памяти написал)
Valen, спасибо, - именно так я и делаю. Но судя по высказываниям уважаемого (не сарказм) Q-Master`a есть более правильный и удобный способ, - таки, хотелось бы подробностей. :)
Oleg N. Cher
13.06.2014, 23:24
фокус не сработает, если в функциях используются "самодельные" типы данных, которые без хедера компилятор не распознает и выдаст ошибку синтаксиса. Не сталкивался с этим, потому что меня умиляет писать типы полностью, например, "unsigned char", а не заменять на свои типа "u8".Да, если описывать типы и прототипы вызываемых функций прямо в теле, то во многих случаях можно обойтись без инклюдов.
В случае с ZXDev спишем накладные расходы по времени компиляции на многократную обработку инклюда SYSTEM.h - это обходится описанием недостающих типов в заголовке (до "линии заголовка"). Конечно куски компилятся сильно дольше, чем один исходник - из-за многократных (по количеству кусков) вызовов SDCC, который ОС надо настроить в памяти, подгрузить ассемблер, линкер и препроцессор, находящиеся в отдельных exe. В случае простых библиотек с десятком функций компиляция происходит секунды. Сейчас вот проверил - вся библиотека XDev компилится < 15 секунд - с разрезанием всех модулей, как положено, а она сейчас состоит из таких модулей:
SYSTEM Platform Strings Console GrScr GrPixel GrTiles GrFonts Math Timer Input
Притом у меня не самый мощный комп, один из первых двухъядерников с 2 Гб ОЗУ. Мне трудно представить ещё большую библиотеку для Спека, тем более, никто не заставляет пихать все модули в одну библиотеку, можно и в разные.
---------- Post added at 22:24 ---------- Previous post was at 21:26 ----------
Но судя по высказываниям уважаемого (не сарказм) Q-Master`a есть более правильный и удобный способ, - таки, хотелось бы подробностей. :)Как понял его способ я: заключить каждую функцию в одном большом исходнике в такие "рамочки":
#ifdef _Function_1_
void Function_1 (void) {
..
}
#endif- и потом скармливать компилятору весь исходник много раз, подпихивая ему в качестве параметра -D_Function_X_
При этом лично для меня очень сомнительно, что разделительные линии воспринимаются намного хуже кучи #ifdef'ов. И сомнительно что хидеры будут инклюдиться только раз, а не по количеству кусков. И это велосипед с квадратными колёсами, как я его понимаю. А сам я езжу на треугольных. ;)
Почему есть трудности с внедрением круглых колёс в SDCC. Есть проблемы, связанные со static-функциями, которые обозначил Vitamin - с тем, что все имена в библиотеке глобальны (так спроектировано) и, возможны ещё некоторые проблемы, вызванными текущим каркасом разработки. Я не знаю как всё это решается в рамках GNU-утилит, надо разбираться.
Q-Master
14.06.2014, 10:29
Я правильно понимаю, что это будет каждый раз, при сборке приложения, которое использует библиотеку?
Стоп-стоп-стоп. Ключевым моментом был как-раз вопрос о ЕЖЕРАЗОВОЙ компиляции библиотеки. Если компиляция происходит один раз, то мой способ ессно не подходит, но в таком случае ручками распилить сорец на ф-ции и собрать как-надо значительно эффективнее чем автораспиливатель.
---------- Post added at 10:29 ---------- Previous post was at 10:20 ----------
Valen, спасибо, - именно так я и делаю. Но судя по высказываниям уважаемого (не сарказм) Q-Master`a есть более правильный и удобный способ, - таки, хотелось бы подробностей. :)
Стоп. Я говорил исключительно про "компиляция каждый раз", ибо рассматривать такой вопрос при линковке с статической либой мягко скажем глупо. В случае сборки библиотеки вообще делать 1 гигантский .с файл неразумно.
Стоп-стоп-стоп. Ключевым моментом был как-раз вопрос о ЕЖЕРАЗОВОЙ компиляции библиотеки. Если компиляция происходит один раз, то мой способ ессно не подходит,
Вот непонятно, что за ежеразовость такая! Можно поподробней, когда этот "раз" наступает?
но в таком случае ручками распилить сорец на ф-ции и собрать как-надо значительно эффективнее чем автораспиливатель.
Кто это должен делать, тот кто подготавливает библиотеку, или пользователь(тот кто пишет прогу, использующую библиотеку) библиотеки?
---------- Post added at 12:44 ---------- Previous post was at 12:36 ----------
Чуток офтопика :) (http://www.newsru.com/arch/world/27may2009/velo.html)
Q-Master
14.06.2014, 10:50
Вот непонятно, что за ежеразовость такая! Можно поподробней, когда этот "раз" наступает?
Насколько я понял, изначально такой вариант и делался. Поэтому я и предложил вариант с #ifdef. В нормальном случае исходники либы представляет из себя изначально кучу .с файлов и не требуют таких извращений.
Кто это должен делать, тот кто подготавливает библиотеку, или пользователь(тот кто пишет прогу, использующую библиотеку) библиотеки?
Тот кто готовит библиотеку ессно. Точнее тот, кто ее собирает в статическую.
Q-Master
14.06.2014, 11:00
При этом лично для меня очень сомнительно, что разделительные линии воспринимаются намного хуже кучи #ifdef'ов. И сомнительно что хидеры будут инклюдиться только раз, а не по количеству кусков. И это велосипед с квадратными колёсами, как я его понимаю. А сам я езжу на треугольных. ;)
Для случаев когда "библиотека" представляет из себя 1 исходник и не подготавливается автором никак:
компиляция в С происходит в 2 этапа: 1-препроцессор, 2-компиляция.
На 1м этапе выполняются все директивы препроцессора, в частности, #ifdef #endif, #warning, #error и тэдэ.
На 2м этапе происходит компиляция подготовленного.
Само собой что никого не интересует кто там в чем сомневается, ибо все инклюды находятся в том-же исходнике (одном) и соответственно включаются 1 единственный раз, т.к. в твоем случае 1 физический файл разрезается на 100500 кусков, а в моем случае компилятор просто ВЫКИДЫВАЕТ из текста ненужное и ничего никуда не режет.
PS: Можно мне пример исходников библиотеки в твоем исполнении, чтобы я таки понял за дело мы спорим или нет?
---------- Post added at 11:00 ---------- Previous post was at 10:58 ----------
Какой "таккой"? Я попросил разъяснить понятие "ежеразовость". Мой вопрос не подразумевает никакого контекста, на который можно сослаться словом "такой".
Ну прочитай данный тред с начала. Я-ж не буду пересказывать все его содержание?!
В моем понимании был такой вариант: библиотека есть мегасорец, который каждый разраб, который его юзает вынужден пилить на куски чтобы нормально линковать в свой проект.
Oleg N. Cher
14.06.2014, 16:38
Странно, я-же просто просил объяснить мне кое что, помочь понять, а в ответ получаю нечто непонятное мне, смахивающее на оправдания.Reobne, перед нами - типичный случай за "умной" формулировкой замылить смысл происходящего. Мне тоже не нравится, что разговор ушёл в область каких-то абстрактных сопоставлений без детальных наглядных примеров, что я и хочу попытаться исправить.
Круглые колёса. Исходники любого содержания, хоть большие, хоть маленькие, хоть с инклюдами, хоть без, хоть со static'ами - всё едино - "умная линковка" из коробки, всё оно так и должно быть. В "правильных" компиляторах всё оно так и есть. Но в "неправильных", куда отнесём и SDCC, ВСЕ сущности из одного исходника попадают в один сегмент (*.rel) библиотеки и если использовать хоть ОДНУ сущность из этого сегмента - потянутся все остальные. Лечится распихиванием различных сущностей по разным исходникам. Остаётся проблема многократного запуска SDCC с его инфраструктурой, многократного парсинга инклюдов - она никуда не делась.
Квадратные колёса (по методу Q-Master). Делаем "резку" цельного исходника "в уме" с помощью препроцессора и #ifdef'ов, как я показал выше. Многократный запуск SDCC и проблема многократной обработки в исходнике инклюдов и static'ов никуда не делась, как бы её ни забалтывали:
#include "MyIncl.h"
#ifdef _ABC_1
void ABC_1 (void) {
}
#endif
#ifdef _ABC_2
void ABC_2 (void) {
}
#endifПусть нам Q-Master пояснит, как он предлагает компилить "в памяти" такую библиотеку с единоразовым запуском компилятора и единоразовой обработкой инклюда. С примерами объяснит и подробно.
Треугольные колёса (smartlib) - та же самая резка, но без #ifdef'ов, а с помощью "линии заголовка" и "линий разреза". При этом вменяемые этому способу проблемы с многократной обработкой инклюдов и static'ами точно и ровно также присутствуют и в "квадратном" варианте колёс.Разумеется, я за правильные круглые колёса, только не вижу как в таком сообществе добиваться поставленных целей. Либо всё делать одному и выслушивать, что асм Z80 круче всего на свете, либо забить, выбирайте.
---------- Post added at 15:38 ---------- Previous post was at 15:15 ----------
в твоем случае 1 физический файл разрезается на 100500 кусков, а в моем случае компилятор просто ВЫКИДЫВАЕТ из текста ненужное и ничего никуда не режет.
PS: Можно мне пример исходников библиотеки в твоем исполнении, чтобы я таки понял за дело мы спорим или нет?Давал уже, но отчего же, извольте.
#include "MyIncl.h" // Здесь то, что надо включать многократно,
// т.е. нужное ВСЕМ кускам.
// Секция заголовка может быть и ПУСТОЙ, т.е. не включать в себя ничего.
// Также она может просто отсутствовать - результат тот же.
/*================================== Header ==================================*/
#include "MyAbc1.h" // А вот здесь можно поместить нужное только ЭТОМУ куску
void ABC_1 (void) {
}
/*--------------------------------- Cut here ---------------------------------*/
#include "MyAbc2.h"
void ABC_2 (void) {
}Как видим, присутствует возможность гибко выбирать какие инклюды включать многократно, какие однократно. Линии разреза наглядны. Фразы "Header" и "Cut here" могут быть убраны, решает только присутствие в комменте определённого количества идущих подряд "===" или "---". Т.е. ничем не хуже, а то и нагляднее вашего способа. А разрезанные файлы ОС кэширует (все мы знаем, что поиск во второй раз происходит во много раз быстрее, чем в первый), так что проблем со скоростью трансляции вообще нет.
Но вы лучше расскажите нам как компилить по вашему способу: во-первых "всё в памяти", а во-вторых - единократным вызовом компилятора (а может ещё и библиотекаря? ;) ), ибо только это мы можем считать твёрдым достоинством квадратных колёс и преимущества их над треугольными. ;)
Oleg N. Cher
15.06.2014, 02:53
Исходники либ есть в ZXDev, ссылки в Пристанище Спектрум-кодера (http://zx.oberon2.ru/forum/viewforum.php?f=10). Дублировать ничего не буду.
Q-Master
15.06.2014, 19:15
Исходники либ есть в ZXDev, ссылки в Пристанище Спектрум-кодера (http://zx.oberon2.ru/forum/viewforum.php?f=10). Дублировать ничего не буду.
Посмотрел сорцы, в частности zxdev. Много монструозных файлов непонятно зачем сделанных именно так и непонятно почему не разбитых на куски.
Отсутствует какая-либо система сборки за исключением кучи батников, соответственно не собирается нигде кроме винды, что печально.
PS: почему не заюзалась cmake?
Oleg N. Cher
15.06.2014, 23:38
Много монструозных файлов непонятно зачем сделанных именно так и непонятно почему не разбитых на куски.Объясняю. Это Си-адаптированные, т.е. заключённые в сишную обвязку Оберон-модули. Соответственно они являются реализацией заявленных Оберон-интерфейсов. Разбить их на куски ручками может и можно, но не нужно. Разбиение утилитой - процедура не ёмкая по времени, занимает доли секунды. И, кстати, нечего придираться к "возможным ошибкам в smartlib", с тем же успехом они где угодно. Такая придирка воспринимается как попытка продолжить спор при отсутствии других аргументов.
Отсутствует какая-либо система сборки за исключением кучи батников, соответственно не собирается нигде кроме винды, что печально.
PS: почему не заюзалась cmake?А вы почему не пользуетесь ant? А если даже и пользуетесь, то почему не пользуетесь proguard? А если даже и пользуетесь, то почему не пользуетесь GNAT? И т.п.
Вполне хватает возможностей и батников, не люблю из пушки стрелять по воробьям, это раз. Два - зачем тянуть лишнюю утилиту в ZXDev. Три - вакантно направление разработки нативного XDev для Linux, кто мешает? Почему я не занимаюсь этим - не вижу смысла утруждать себя линуксом, потому что прекрасно обхожусь виндой. А юзерам всё равно под какой ОС собраны игры.
P.S. Ну так что там насчёт "компиляции в памяти"? А то Reobne попросил объяснить, но объяснений так и не дождался. Зачем водить за нос человека?
Oleg N. Cher
16.06.2014, 02:20
Давайте чтобы у нас был предмет беседы сопоставим треугольные и квадратные колёса, и уж, так и быть, пусть не на схематической, а на реальной библиотеке NewSupercode, которую приаттачиваю. Собирается примерно таким батником (пути опускаю для простоты восприятия):
@IF EXIST %1.lib DEL %1.lib
smartlib %1.c
@FOR %%i IN (%1_0??.c) DO (
..\Bin\sdcc -c %%i -mz80 --opt-code-size --disable-warning 59 --disable-warning 85 -I "." -I include -I Obj
@IF errorlevel 1 PAUSE
)
@FOR %%i IN (%1_0??.rel) DO ..\Bin\sdar -rc %1.lib %%i
@Bin\clearКомментирую.
@IF EXIST %1.lib DEL %1.lib - удаляется старая версия библиотеки, если она существует. Были проблемы с аддитивно-инкрементальным добавлением фрагментов, поэтому советую всегда так делать.
smartlib %1.c - резка файла Name.c на куски Name_001.c, Name_002.c, ... Происходит она моментально.
Дальше в цикле компилируем. Есть возможность компилировать весь исходник целиком (по F11), это происходит быстро. Если он скомпилировался, можно собрать его в библиотеку с разрезанием (по F12), тогда компилируются нарезанные фрагменты. Если при компиляции фрагмента произошла ошибка, возникает пауза.
Дальше в цикле формируем из скомпилированных объектников Name_001.rel, Name_002.rel, ... целую библиотеку. И чистим временные уже ставшие ненужными фрагменты, как *_???.с, так и *_???.rel
Не претендую на сверхидеальность - я даже к этой схеме подходил несколько лет. Предложения по улучшению процесса с благодарностью принимаются. Только не в стиле "так лучше потому что я всегда так делаю", пожалуйста. Здесь достаточно умных людей, чтобы оценить преимущество квадратных колёс над треугольными, если такие преимущества имеют место быть.
Ну а теперь пусть нам Q-Master блеснёт профессионализмом и покажет как именно он с помощью cmake предлагает решать проблему "умной линковки". С учётом того, что мейк-файл - это, в принципе, тот же скрипт (как и батник), только под управлением другого интерпретатора. Вопрос привычки понят, но зачем переходить на другой интерпретатор, к тому же пришлый, вместо нативного, возможностей которого тоже хватает?
Люди Linux-мира не мыслят своей работы без хорошего мейка, но это особенно важно для больших и сверхбольших проектов. Впрочем, этот вопрос для меня не нов, он уже обсуждался у нас на форуме в теме use makefiles (http://zx.oberon2.ru/forum/viewtopic.php?f=8&t=137), поднятый как раз ценителем ценностей Linux-мира, который преспокойно разобрался в ZXDev и смог построить свой рогалик на Обероне (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=125), не выходя из своего любимого Linux'а и даже без Wine. Я не верю, что славяне менее способны. :)
Притом просьба, чтобы Q-Master это сделал рабочим собирающимся примером этой же библиотеки. И без фраз типа "Много монструозных файлов непонятно зачем сделанных именно так", потому что если критика конструктивна, то хотелось бы и фраз конкретных. Что именно кажется непонятно "зачем сделанным именно так и монструозным"? Как именно предлагается избежать монструозности? Если библиотека сама по себе большая "на 100500 кусков", то она всё равно монструозна количеством кусков, и с разрезанием, и без оного тоже.
А чо классный рогалик. и весит всего 35кб
Q-Master
16.06.2014, 17:13
Я прошу прощения что сделал именно так, но вот кусок либ z80 собирающихся с помощью cmake sdcc и sdasz80.
Там-же newsupercode.
PS: почему cmake? потомучто батники работают исключительно на винде и аццки неудобны для автоматизации сборки.
PS1: не нашел примера.
Oleg N. Cher
16.06.2014, 18:27
Примера чего? И зачем ты поразрезал всё на кусочки? Ты же тут пол-ветки нам рассказывал как надо всё правильно делать без разрезания. Где пример?
Батники аццки удобны тем, кто к ним привык, и для кого линукс - чужая сторона. Для меня командные файлы .sh аццки неудобны тем, что их можно запускать только под чужеродной для меня системой.
Наверное всё-таки разбираюсь, раз писал для Java ME, притом автор Java Гослинг не отицает, что изучал исходники Оберон-системы. Да тут аналогии с Обероном самые прямые.
Значит, не составит труда ответить на вопросы:
1) что такого означает "раздельная компиляция" раз ее нет в С++?
2) почему почти все ссылки на сравнения оберона с другими языками такие древние? В вышеупомянутой статье (какого она года, кстати? webarchive дает последний слепок 2009 года) ссылаются на журнал аж 98 года
3) на странице http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=92 проскальзывает цитата
Думаю, ясно, как из всего этого получается инкапсуляция, наследование и полиморфизм.
Я тупой валенок, прошу продемонстрировать работу всех трех принципов на фрагменте "простого Си без плюсов"
Oleg N. Cher
17.06.2014, 03:24
Значит, не составит труда ответить на вопросы:
1) что такого означает "раздельная компиляция" раз ее нет в С++?Встречный вопрос: какое отношение имеет "раздельная компиляция" в C++ к Java?
2) почему почти все ссылки на сравнения оберона с другими языками такие древние?Лучше скажи "почти все, которые я читал, а читал мало". Ну да, та статья старая. Но актуальная.
Я тупой валенок, прошу продемонстрировать работу всех трех принципов на фрагменте "простого Си без плюсов"Пожалуйста.
Инкапсуляция. Юзаем static процедуры и static переменные. Их извне не видно, получаем спрятывание, инкапсуляцию. Если на уровне объекта, то объектом выступает структура, её мы также делаем static.
Наследование. Делай так. Закажи себе структуру типа:
struct a { int a, b, c; } a;
struct naslednic_a { int a, b, c, d, e, f; } naslednic;
Теперь приводи насильственно тип a к типу naslednic_a и работай. Никто не обещал, что будет удобно.
Полиморфизм. Я не знаю, что это за извращение. ;) А тебе известно, что объектный Оберон-2 транслируется в Си без плюсов? А известно, что первая реализация C++ была просто транслятором C++ в обычный Си? Если да, то зачем задавать тупые вопросы? Если нет, то фи сишнику. ;)
xor a
out (#fe),a
намного производительнее. Если отказаться от в 100500 раз более тормознутой Basic'овской CLS.Да? И что будет после следующего BEEP'а? Нет уж, если делать Basic'овский BORDER, то делать его по уму. Ну и CLS ты приплёл совершенно не к месту. При чём здесь, в данном случае CLS вообще?
Ещё не пойму: зачем придираться к СХЕМЕ? Хорошо, вот как устроен BORDER всамделишне:
#define __hash__ #
#define __id__(x) x
#define __ld_a__(x) if(x==0) {__asm xor a,a __endasm;}else{__asm ld a,__id__(__hash__)x __endasm;}
...
import void Basic_BORDER_stdcall (SHORTINT color);
#ifndef BORDER_fastcall
#define Basic_BORDER Basic_BORDER_stdcall
#else //BORDER_fastcall
#define Basic_BORDER(color) __ld_a__(color); \
__asm \
call 0x229B \
__endasm;
#endifТ.е. он в случае всегда константного аргумента устроен именно так, как я сказал:
__ld_a__(color) - загрузка в рег. A кода цвета
call 0x229B - вызов процедуры из ПЗУ
И правильно, и с корректной работой после BEEP'а.
Встречный вопрос: какое отношение имеет "раздельная компиляция" в C++ к Java?
Задай вопрос автору таблички, в которой данный аспект фигурирует в сочетании с обероном, явой и с++. Так что жду ответа.
Ну да, та статья старая. Но актуальная.
Я верю, что статья 19хх года очень актуальна про оберон. Про его "конкурентов"- врядли.
Инкапсуляция. Юзаем static процедуры и static переменные. Их извне не видно, получаем спрятывание, инкапсуляцию. Если на уровне объекта, то объектом выступает структура, её мы также делаем static.
Каким боком расположение экземпляра класса в статической памяти делает скрытым его внутреннее строение?
Теперь приводи насильственно тип a к типу naslednic_a и работай. Никто не обещал, что будет удобно.
"20 раз вокруг ноги, сквозь штанину в сапоги". Что будет нелегко- это очевидно, но искусственное придумывание трудностей- это уже перебор (зато можно поорать про "огромную проделанную работу")
Я не знаю, что это за извращение - не смейся
Тогда какого хрена ты с умным видом рассуждаешь, что "это извращение" реализуется на С? Да, реализуется. Вот и продемонстрируй.
А тебе известно, что объектный Оберон-2 транслируется в Си без плюсов?
В таком случае приведи пример полиморфизма на объектном Обероне-2.
Да, реализуется. Вот и продемонстрируй.
Ты знаешь, что реализуется. Человек тебе говорит что не вникал в суть полиморфизма. Смысл требовать демонстрации?
Вообще полиморфизм интересный программистский подход. Он-же в голове должен быть. Некоторые языки позволяют его описывать более явно, и только.
На ПМК с ним конечно не развернуться. :) А на Z80 ассемблере вполне. Даже если-бы JP (HL) не было, можно PUSH DE, RET. В отличии от явного подхода, тут полная свобода. Какие хочешь методы, прямо в поля объекта пиши адреса, какие хочешь - в таблицы виртуальных функции класса собирай, а в объекте только адрес таблицы. Динамически меняй.
В Си тоже запрсто. Процедурные типы есть. Функции с параметрами описываются легко.
Вот в ZX бейсике, GOSUB X можно сделать, а параметры передавать неявно - некрасивее будет.
Посмотри внимательно. Для SDCC тоже почти никто почти ничего не делает. К тому же если кому-то нравится ZXDev, но не нравлюсь я, кто ему мешает программировать на ZXDev в своё удовольствие? Просто не нужно связывать эти вещи.
ну да Чурера она на z88dk.
а вот EVO sdk оно уже на sdcc.
Oleg N. Cher
17.06.2014, 18:05
ну да Чурера она на z88dk.Можно юзать в качестве бэк-энда ZXDev и z88dk, и SpritePack(SPLIB) к нему впридачу, дело техники. Как говорится, было бы желание.
introspec
17.06.2014, 18:08
Здесь у нас монополия на кодерскую крутость. А ты понимаешь, что для продвижения Оберона в любых кругах нужно иметь авторитет. А как отвоевать его у монополистов, которые выходят на пиписькомер, игнорируют контраргументы и выдвигают новые задачи.Это реально очень легко делается. Просто приходишь, выкладываешь новый красивый софт на Обероне и все радостно утираются. Ключевые слова: новый (легко), красивый (твои крысиные бега не катят, например), софт.
Без нового красивого софта ничего кроме критики ты не увидишь, потому что я, равно как и многие другие люди в этом треде, реально не верят, что твоя связка позволяет делать новый красивый софт.
Никто тебе не обещал на голом Си таких извращений, которые вообще немыслимы без виртуальной машины.
Ну покажи реализацию полиморфизма в любой другой объектной модели. Чтоб попроще было. "Наследование" же продемонстрировал.
Ну так читай предложенную книгу, исправляйся.
Я не использую оберон, но и не ругаю его. Равно как и другие технологии, в которых слабо разбираюсь. В отличие от.
Ну покажи реализацию полиморфизма в любой другой объектной модели. Чтоб попроще было. "Наследование" же продемонстрировал.
я наверное не в теме дискурсии (не люблю срачи, они явно к хорошему не приводят)
но это не то что вы спрашиваете ?
https://en.wikipedia.org/wiki/GObject
The GLib Object System, or GObject, is a free software library providing a portable
object system and transparent cross-language interoperability.
GObject is designed for use both directly in C programs to provide object-oriented
C-based APIs and through bindings to other languages to provide transparent cross-language
interoperability, e.g. PyGObject.
Objective C долгое время транслировался в С и компилился обычным C компилиром
там объектная модель в библиотеке.
Ну так под стать другим, под предлагаемый формат общения. Или, думаешь, формат "мы сами не местные, а я бедный родственник" был бы эффективнее? ;)
ну можно было просто снять корону и зайти как равному, с аргументом в руках. Например показать тот же самый earthraid написаный на обероне, или болдердаш, кстати говоря.
Мою железную аргументацию во многих постах никто не пробил, просто проигнорировали. А задачи мне подсовывают чтобы свою писю потешить - из "задачедателей" всё равно никто ничего не собирается делать.
Задачи тебе предлагают в ответ на слова твои о том что: "Её переписать на Оберон - раз плюнуть. Машкод станет короче в полтора раза."
Но хочется обратить твое внимание что несмотря на огромное количество плюнутой тобой слюны результата я не вижу.
результаты же различной тяжести "hello world" не интересны ниразу.
Задачедатели заняты скорее всего чем то другим.
Честный программист должен себе признаться в той или иной степени готовности его программы. ;)
что скажешь вот про эту программу?
http://www.worldofspectrum.org/infoseekid.cgi?id=0017730&loadpics=3
и например вот про эту
http://zx.pk.ru/showpost.php?p=712414&postcount=44
они завершены или нет?
Q-Master
17.06.2014, 20:45
Примера чего? И зачем ты поразрезал всё на кусочки? Ты же тут пол-ветки нам рассказывал как надо всё правильно делать без разрезания. Где пример?
Батники аццки удобны тем, кто к ним привык, и для кого линукс - чужая сторона. Для меня командные файлы .sh аццки неудобны тем, что их можно запускать только под чужеродной для меня системой.
Ты просил пример тебе собрать, который в архиве. В архиве примера небыло.
Порезал потому что я про линковку компайл-тайм рассказывал, а тут статические либы, которые линкуются нормально и так.
Батники и sh файлы тут не нужны. В данном случае просто для примера приведен. Все делается системой сборки, зато везде одинаково.
---------- Post added at 20:45 ---------- Previous post was at 19:59 ----------
Objective C долгое время транслировался в С и компилился обычным C компилиром
там объектная модель в библиотеке.
ObjC вообще нельзя брать в пример в данном случае. Он имеет совершенно другую объектную модель. Объект в обжцэ всегда наследник NSObject и фактически не имеет ф-ций. И уж тем-более ни одна из них не вызывается снаружи объекта.
Тип может передаваться любой, в том числе неизвестный, лишь бы удовлетворял протоколу.
Если он обязательно наследован от определённого типа, то не считается?
я наверное не в теме дискурсии (не люблю срачи, они явно к хорошему не приводят)
но это не то что вы спрашиваете ?
Одна из промышленных реализаций.
Я всего-навсего попросил Oleg N. Cher подтвердить его же собственные слова по поводу легкости реализации принципов ООП на чистом С. Из трех принципов только по одному было что-то с натяжкой похожее на ответ. Что какбэ намекает на уровень знаний по данному вопросу, слабо соотносящийся с апломбом заявлений.
ну можно было просто снять корону и зайти как равному, с аргументом в руках.
+100
Респект и уважуха за деятельность типа ZXDev, но зачем обманывать себя и других?
Если он обязательно наследован от определённого типа, то не считается?
Не совсем понял, но примерно догадываюсь о чем речь.
Если этот определенный тип описывает полиморфное поведение, то да. В идеальном случае- является интерфейсом/протоколом.
ObjC вообще нельзя брать в пример в данном случае. Он имеет совершенно другую объектную модель. Объект в обжцэ всегда наследник NSObject и фактически не имеет ф-ций. И уж тем-более ни одна из них не вызывается снаружи объекта.
Почему?
Как по мне, так модель с посылкой сообщений - более правильная чем плюсовая :)
Alcoholics Anonymous
18.06.2014, 00:23
Одна из промышленных реализаций.
Я всего-навсего попросил Oleg N. Cher подтвердить его же собственные слова по поводу легкости реализации принципов ООП на чистом С. Из трех принципов только по одному было что-то с натяжкой похожее на ответ. Что какбэ намекает на уровень знаний по данному вопросу, слабо соотносящийся с апломбом заявлений.
Я, вероятно, не может в полной мере следить за ходом дискуссии из-за языкового барьера, но у меня есть трудное время, чтобы понять, почему есть споры.
Принципы ООП существовали задолго до термин ООП был популярным. C + + сам начал в качестве предварительного процессора, что выход чистого C код, который затем был составлен компилятором C. Инкапсуляции данных, наследование, полиморфизм были все переведены на C кода.
Метод связывания, что Олег описывает, с участием имя-коверкая и вырезания объектов в 500 000 штук не был изобретен Олег - это была вокруг в течение десятилетий, и точно, как C + + компиляторов работы. Разница лишь в том вы не видите все эти файлы, как разрезы компилятора вещи и ставит его в один файл объекта. Предварительно скомпилированные заголовки и постепенно компиляции в объектные файлы являются как этот процесс ускорился.
Другой aternative помощью # IFDEF * не * эквивалентны и используется только когда инструменты, чтобы сделать это автоматически не доступны.
Примеры методов ООП, я могу предложить некоторые в z88dk реализованного в z80 ассемблере. Я не вижу никакой разницы между С и z80 ассемблере поэтому они должны служить в качестве заменителя.
У нас есть несколько контейнеров в z88dk по образцу C + + STL. Все это реализовать Отношения наследования [/ B]. Один простой пример: "массива байтов" является одним из основных тип, который может хранить фиксированный размер массива байтов. Он определяет операции для добавления, индекс, скопируйте строки в / из и т.д. "байт Vector" наследует от "массива байтов". Все "массив байт" функции можно также назвать на "байт Вектор». Но "Байт Вектор" добавляет операций, которые позволяют основной массив для выращивания или сократилась с помощью Realloc (). Это наследство вместе с увеличением подкласса. Это очень легко сделать в C или ассемблере, устраивая иметь данные в "базового класса" появляются в начале структуры "подкласса".
[B] инкапсуляции данных [/ B], еще один принцип ООП. Конечно, инкапсуляции данных существует уже с начала вычислений. Под С его называют "абстрактные типы данных" и легко реализуется с помощью структуры для хранения личных данных и публичный интерфейс, доступный как документально функции, принимающие указатели на структуры в качестве параметра. В z88dk, одним из примеров является библиотека SP1 спрайт.
Полиморфизм. Это один видно реже. В z88dk мы используем полиморфизм в STDIO. Файл (данные) + его водитель (методы) представляют собой полиморфный объект. Вид полиморфизма мы используем это как то, что находится в Smalltalk и Java. Как Smalltalk, это делается через передачи сообщений и, как Java, мы указываем интерфейсы, что водители должны быть реализованы.
Интерфейс STDIO содержит сообщения типа "putc", "читать", "писать" и т.д. Все Printf / зсапЕ / поиск / и т.д. операции переводятся в небольшом количестве сообщений, каждый из которых идентифицируется байта. Файловая структура, что эти сообщения отправляются содержит z80 JP инструкцию для водителя. Водитель декодирует сообщение с помощью переключателя о "CP STDIO_MSG_READ", и переходит к правильному действию.
В дополнение к STDIO интерфейс, есть консольный интерфейс для текста ввода / вывода на экран, интерфейс символов для таких вещей, как последовательных устройств, а также интерфейс диска для дисковых устройств. Эти интерфейсы реализованы все таким же образом с использованием сообщений.
Мы также почти сделать обобщенное программирование как несколько библиотек используют понятие итераторов. Библиотека спрайт SP1 имеет несколько функций итераторов пройти списки символов квадратов обновить на экране, списки экраном плитки, списки спрайтов но эти списки одного типа объекта. В С (или ASM) это очень легко сделать их списки любого вида объект, реализующий определенный интерфейс. Все что нужно, это каждая структура в списке нуждается указатель на функцию, функции, реализующей операцию. Поскольку указатель функции является членом структуры, каждый элемент в списке может быть другой объект, и вот еще один пример как обобщенное программирование и полиморфизм.
Чем сильнее тип полиморфизма реализовать то, что сделано с виртуальными функциями, так что это видели реже. Но это может быть сделано путем иметь массивы указателей на функции, которые реализуют методы каждой части объекта.
Все эти вещи были сделаны в С, так как его ранней истории. C + + просто обеспечивает поддержку компилятора просто реализовать эти функции, что означает меньше ошибок и более сложные программы.
===
I probably can't fully follow the discussion because of the language barrier, but I have a hard time to understand why there is controversy.
OOP principles existed long before the OOP term was popularized. C++ itself started as a pre-processor that output pure C code that was then compiled by a C compiler. Data encapsulation, inheritance, polymorphism were all translated to C code.
The linking method that Oleg describes, involving name-mangling and cutting objects into 500,000 pieces was not invented by Oleg -- this has been around for decades and is exactly how C++ compilers work. The only difference is you don't see all those files as the compiler cuts stuff up and puts it into a single object file. Pre-compiled headers and incrementally compiling into object files are how this process is sped up.
The other aternative using #ifdef is *not* equivalent and is only used when the tools to do this automatically are not available.
For examples of OOP techniques, I can offer some in z88dk implemented in z80 assembler. I don't see any difference between C and z80 assembler so they should serve to act as substitute.
We have several containers in z88dk modelled on C++ STL. These all implement [B]inheritance relationships. One easy example: "Byte Array" is a fundamental type that can store a fixed size array of bytes. It defines operations to append, index, copy strings to / from, etc. "Byte Vector" inherits from "Byte Array". All "Byte Array" functions can also be called on a "Byte Vector". But "Byte Vector" adds operations that allow the underlying array to be grown or shrunk via realloc(). This is inheritance along with augmentation of the subclass. It's very easy to do in C or asm by arranging to have the "base class's" data appear at the beginning of the "subclass's" structure.
Data encapsulation is another OOP principle. Of course, data encapsulation has been around since the beginning of computing. Under C it is called "Abstract Data Types" and is easily implemented using structures to hold private data and a public interface available as documented functions taking pointers to the structure as parameter. In z88dk, one example is the sp1 sprite library.
Polymorphism. This one is seen less often. In z88dk we use polymorphism in stdio. A FILE (data) + its driver (methods) constitute a polymorphic object. The kind of polymorphism we use is like what is found in smalltalk and Java. Like smalltalk, it's done through message passing and like Java, we specify interfaces that the drivers must implement.
The stdio interface contains messages like "putc", "read", "write", etc. All printf/scanf/seek/etc operations are translated into a small number of messages, each one identified by a byte. The FILE structure that these messages are sent to contains a z80 JP instruction to the driver. The driver decodes the message using a switch statement "CP STDIO_MSG_READ", and jumps to the correct action.
In addition to the stdio interface, there is a console interface for text i/o to the screen, a character interface for things like serial devices, and a disk interface for disk devices. These interfaces are all implemented in the same way using messages.
We also almost do generic programming as several libraries use the concept of iterators. The sp1 sprite library has several iterator functions to traverse lists of character squares to update on screen, lists of screen tiles, lists of sprites but these are lists of one type of object. In C (or asm) it is really easy to make them lists of any kind of object implementing a specific interface. All that is needed is each structure in the list needs a function pointer to a function implementing the operation. Because the function pointer is a member of the structure, each item in the list can be a different object and here is another example of both generic programming and polymorphism.
The harder type of polymorphism to implement is that done with virtual functions, so it's seen less often. But this can be done by having arrays of function pointers that implement the methods of each part of the object.
All these things have been done in C since its early history. C++ just provides compiler support to simply implement these features which means fewer errors and more complex programs.
Из трех принципов только по одному было что-то с натяжкой похожее на ответ.
Ну вот на счёт инкапсуляции. Как это можно продемонстрировать? Это-же что-то типа принципа не применять GOTO. Если в языке уже нет оператора GOTO то это уменьшает возможности программисту ошибиться. А если в языке есть GOTO, ну что-же, не применяй его "вручную" :). Так и инкапсуляция. Это языковые рельсы, которые жёстко не дают съехать с пути. Нет рельсов - рули сам, ответственность на программисте.
Хотя я не знаю так хорошо Си, возможно можно на предпроцессоре накрутить какието assert-ы, чтобы рельсы всё-таки были. Вот, раз ты эксперт, взял-бы да рассказал.
Oleg N. Cher
18.06.2014, 09:24
Вот такой-сякой полиморфизм наследования (http://zx.oberon2.ru/forum/viewtopic.php?f=25&t=177&start=30#p1016) на Обероне. В голый Си переводится по аналогии. Я, правда, не уверен, что Vitamin впечатлится, ему, видимо, непременно нужен такой вид полиморфизма, который совместим только с виртуальной машиной фирмы Microsoft. Но увы, чудес на свете не бывает.
Скорее речь шла об этом: http://en.wikipedia.org/wiki/Oberon-2_%28programming_language%29#WITH_statement
Alcoholics Anonymous, you are absolutely right!
Basic OOP principles are extremely simple but very powerfull. And should not be associated only with languages like C++/Java/ObjC - they only provides syntax sugar and hides a lot of machinery you should care about while implementing the same on C/asm. So, you can share my sarcasm for talks about how OOP is sux because OOP=C++/Java/ObjC.
Ну вот на счёт инкапсуляции. Как это можно продемонстрировать?
Например так:
struct MyObject;
void MyObject__Foo(struct MyObject* this, int param);
Все. Кишки MyObject не видны наружу. Для пущего сокрытия можно даже не использовать forward declaration, но это уже хардкор, имхо.
А Олег честно сказал что не вполне сам знает, что при сравнении языков пользовался оценками экспертов. Что ещё надо?
Под нажимом и после уверток- это честно?
Зачем упорно доказывать тому, кого считаешь дураком, что он дурак? Если он дурак, то он не поймёт, если он не дурак, то ты не прав. В любом случае это бессмысленно.
Я стараюсь воздерживаться от подобных оценок, хотя это и нелегко. В отличие от, проявляющего агрессию в ответ на любое уточнение.
Я, правда, не уверен, что Vitamin впечатлится, ему, видимо, непременно нужен такой вид полиморфизма, который совместим только с виртуальной машиной фирмы Microsoft.
А можно подробнее? Что за виртуальная машина фирмы Microsoft? А то я слышал только про Virtual PC, Virtual Server и HyperV.
Shadow Maker
18.06.2014, 10:18
Так, я смотрю аргументы уже кончились. Пошли оценки друг друга. Давайте или как-то ближе к теме, или закроем, а то опять один флуд.
Q-Master
18.06.2014, 20:32
Почему?
Как по мне, так модель с посылкой сообщений - более правильная чем плюсовая :)
А никто и не спорит, но там ООП реализуется по другому и значительно легче конвертируется в С. Яркий пример такого ООП Амижный MUI.
А никто и не спорит, но там ООП реализуется по другому и значительно легче конвертируется в С. Яркий пример такого ООП Амижный MUI.
тут вопрос не в "легче конвертируется в С", а в модели ООП в принципе
она от smalltalk вроде как корни ведёт,
это просто РАЗНЫЕ подходы.
Я прошу прощения что сделал именно так, но вот кусок либ z80 собирающихся с помощью cmake sdcc и sdasz80.
А где собранные либы-то? ;)
Не понял, каким образом в сборку либ вовлекается sdar или sdcclib.
Q-Master
20.06.2014, 20:27
А где собранные либы-то? ;)
Не понял, каким образом в сборку либ вовлекается sdar или sdcclib.
mkdir build
cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain/sdcc.toolchain.cmake
make
profit.
Oleg N. Cher
01.10.2014, 13:41
So, you can share my sarcasm for talks about how OOP is sux because OOP=C++/Java/ObjC.OOP is not sux. Illiterate usage of OOP is sux (http://zx.oberon2.ru/forum/viewtopic.php?f=25&p=1309#p1309). Especially because the OOP approach is possible in any language, to a greater or lesser extent. What was the main message of my posts.
ООП, да и каждый из перечисленных языков, помимо достоинств, имеет несомненные специфические недостатки. Указывать на них != очернять их.
А можно подробнее? Что за виртуальная машина фирмы Microsoft? А то я слышал только про Virtual PC, Virtual Server и HyperV.Я имел ввиду .NET
P.S. Это не попытка продолжить с тобой бесполезный трёп, просто отвечаю на вопрос, закрываю хвост. Буду рад, если ты не станешь разводить демагогию и дальше. Оставляю за собой право личного выбора кого считать хорошим программистом - Вирта, Гуткнехта или, например, тебя.
P.P.S. Textator не впечатлил. Отстой. И кому нужна такая софтина? :v2_dizzy_otvyan:
OOP is not sux. Illiterate usage of OOP is sux.
Absolutely agree!
ООП, да и каждый из перечисленных языков, помимо достоинств, имеет несомненные специфические недостатки. Указывать на них != очернять их.
Разумеется. Но разговор, ЕМНИП, шел о том, что "ООП- отстой!" Провокационное название подразумевает дискуссию. Она и случилась. В чем проблема? Если ты из нее не извлек для себя ничего нового, могу только грустно вздохнуть на эту тему.
P.P.S. Textator не впечатлил. Отстой. И кому нужна такая софтина?
Тебя кто-то заставлял пользоваться? Сочувствую...
Лучше бы заставил прочесть историю создания, а также посмотреть на дату создания...
P.S. ЧСХ, про ZXTune впечатления на этом форуме не было (на другом было). Наверное, чтобы не разбавлять серые тона повествования:)
Oleg N. Cher
01.10.2014, 14:27
Разумеется. Но разговор, ЕМНИП, шел о том, что "ООП- отстой!"Разговор вообще-то шёл об "умной" линковке. Ты меня обвинил в увёртках, но как получилось так, что от "умной" линковки тема резко свернула в сторону ООП? Аргументы закончились, решил слезть на тему, где у тебя более подвешен язык, да?
Провокационное название подразумевает дискуссию. Она и случилась.Только не там, где она уместна, а где можно покрасоваться перед публикой.
P.S. ЧСХ, про ZXTune впечатления на этом форуме не было (на другом было). Наверное, чтобы не разбавлять серые тона повествования:)Не возникло желания попользоваться. Как у тебя ZXDev'ом. Могу только грустно вздохнуть.
denpopov
01.10.2014, 14:35
Oleg N. Cher, долго молчал. в Днипропетровське застрял?
но как получилось так, что от "умной" линковки тема резко свернула в сторону ООП
Да очень просто- ты постоянно ссылаешься на статьи на своем форуме. Вот я и решил походить-почитать. Возникли вопросы.
Только не там, где она уместна, а где можно покрасоваться перед публикой.
Т.е. публика- здесь, а уместно- на твоем форуме? И не скучно тебе там, без публики-то?
Не возникло желания попользоваться. Как у тебя ZXDev'ом. Могу только грустно вздохнуть.
А textator к чему упомянул? Что-то типа придирки к опечаткам или таки возникло желание попользоваться?
Oleg N. Cher
01.10.2014, 15:13
Да очень просто- ты постоянно ссылаешься на статьи на своем форуме. Вот я и решил походить-почитать. Возникли вопросы.А ты почему ответил не на саму статью, а на заголовок? Ты тему-то читал целиком? Потому что если бы да, то не писал бы того, что писал. А так похоже, что ты ответил только на заголовок. Притом в пику мне, но в таких аргументах, с которыми я и сам согласен.
И не скучно тебе там, без публики-то?Там спокойная рабочая обстановка. Конечно хотелось бы побольше интересных собеседников, но где их взять-то. В наше время информационного потопа люди думают не о новой информации, а о том как бы себя оградить от лишней информации. И это закономерно.
А textator к чему упомянул? Что-то типа придирки к опечаткам или таки возникло желание попользоваться?Не возникло. Просто удивился вслух зачем ты его рекламируешь. Если самое ценное в нём - это история создания.
А ты почему ответил не на саму статью, а на заголовок? Ты тему-то читал целиком? Потому что если бы да, то не писал бы того, что писал. А так похоже, что ты ответил только на заголовок. Притом в пику мне, но в таких аргументах, с которыми я и сам согласен.
Сейчас уже не упомню, но за темой следил и читал все что пишут. В том числе и упоминаемую статью.
Раз согласен в аргументах, но не согласен с выводами, значит не учтен какой-то неозвученный фактор. Всего-навсего.
Конечно хотелось бы побольше интересных собеседников, но где их взять-то.
Чисто человеческий совет: определись с целями. Узкоспециализированные разговоры привлекут маленькое количество людей. Провокационные, затрагивающие смежные области привлекут много. Но будь готов ответить на разные вопросы и столкнуться с разными мнениями.
Не возникло. Просто удивился вслух зачем ты его рекламируешь. Если самое ценное в нём - это история создания.
Для тебя- история, для меня- не только.
Oleg N. Cher
01.10.2014, 15:48
Узкоспециализированные разговоры привлекут маленькое количество людей.Для широкоспециализированных разговоров нужны широты, которых не в силах охватить один человек. Ты неверно понимаешь мои мотивы, если думаешь, что я хочу туда затащить кого попало. Опыт показывает: достаточно пары энтузиастов, чтобы форум заиграл. А десять других скучающих челов сделают его только хуже. Но и таких же не поубиваешь из плюсомёта. ;)
Для тебя- история, для меня- не только.Для меня - и не история. Своими историями богаты. Тем и дорожим.
denpopov
01.10.2014, 17:01
Oleg N. Cher, перестаньте лезть в мою личку с непристойными предложения "пойти в жопу". У меня не стоит на суровых бородатых хипарей, мне девачки нравятся.
Мне вот интересно, Оберон попадается на образах дисков для различных компьютеров(Apple Macintosh+)
Неужели это ***** до сих пор имеет практическое применение или оно только инструмент для демонстрации словесной пикировки?
Oleg N. Cher
01.10.2014, 17:03
Вообще да, имеет. Только, видимо, не всем доступны такие высоты восприятия.
denpopov
01.10.2014, 17:19
Ты если уж решил вылить свою неприязнь к украинским националистам, поищи себе других адресатов.
Нука-нука, где это было?
Для меня - и не история. Своими историями богаты. Тем и дорожим.
Да дорожи, кто ж тебе мешает-то? Как баба, ей-богу: сам придумал- сам обиделся.
Oleg N. Cher
01.10.2014, 17:32
Я не обиделся. Каждый кулик своё болото хвалит. Маленькое и малоуютное для других. Особенно на первый взгляд.
Я не обиделся. Каждый кулик своё болото хвалит. Маленькое и малоуютное для других.
А чего на мое болото наехал? Показалось, что в твое плюнул? Ну так приведи пример где я говорил что-то плохое о ZXDev.
Да ты перечитай свои посты в ветке про ZXDev, полные самовоодушевления и желания давать советы свысока.
Еще раз спрашиваю: приведи пример моей критики ZXDev.
Для альтернативно одаренных: не критики Oberon, процедурного подхода а именно продукта.
Да какая разница что именно хаять, это ж не хвалить.
И этот человек мне пеняет, что я невнимательно читаю...
http://zx-pk.ru/showpost.php?p=717891&postcount=59
Oleg N. Cher
01.10.2014, 18:21
Для альтернативно одаренных: не критики Oberon, процедурного подхода а именно продукта.Ты как-то стереотипно мыслишь. По-твоему, если ты уколол человека иголкой, то он должен отомстить тебе непременно тем же способом? А я тебя уверяю - вовсе нет, можно и любым другим удобным.
Q-Master
01.10.2014, 22:08
Олег, а все-же скажи, почему нельзя причесать исходники zxdev и оформить 1 раз корректное разбиение файлов по ф-циям и нормальные хедеры и не делать это каждый раз при каждой компиляции да еще и с диким оверхедом?
Oleg N. Cher
01.10.2014, 23:10
Ну здрасьте, опять двадцать пять. А ты ответь что значит в твоём понимании "нормальные хедеры" и "с диким оверхедом"?
Второй вопрос. Почему ты всё ещё не запускал ZXDev? Барьер вхождения?
Поясняю. Раз ZXDev - это Оберон-среда, то логично делать всё в Оберон-стиле. Писать библиотеки и модули на Обероне. Модуль на Обероне != одна сишная функция, помещённая в один маленький текстовый файл.
Мы хотим писать на Обероне, но вынуждены по некоторым причинам (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=29&p=1303#p1303) транслировать Оберон-исходники в Си. Поскольку у нас есть желание иметь возможность разрабатывать библиотеки и на Обероне, и на Си, мы вырабатываем единостильный подход. А ещё у нас есть желание не терять возможность использовать старые Си-компиляторы, например, Turbo C. А конкретно для Спека мы включили в дистрибутив SDCC, который навязывает нам понятие "модуль == одна функция в одном текстовом файле". А мы хотим транслировать Оберон-модули в Си и собирать их автоматически. А с одного Оберон-модуля получается такой оттранслированный сишный исходник, который не содержит в себе предпосылок для "умной линковки". Оберон-модуль - это более цельная единица, чем сишная функция, зачем-то засунутая в отдельный текстовый файл, понимаешь? И ничего с этим не поделаешь. Но это и не недостаток, я считаю.
Манечка "разрезать библиотеку на кусочки по функциям" навязывается тебе инструментарием. Я это делаю утилитой и автоматически. Ты это делаешь ручками. Какой в этом смысл, объясни? А я тебе скажу. Ты так привык, и ничего пересматривать не хочешь. Ну и бог с тобой.
P.S. Vitamin'у. Ты какой-то неадекват. То ты Absolutely agree! (http://zx-pk.ru/showpost.php?p=741648&postcount=72) с тем, что программировать в ООП-стиле можно и без прямой поддержки ООП в языке, то заставляешь меня показывать тебе как это может быть устроено на Си. Я что, обязан это для тебя делать? Обязан отвечать за каждую букву всех постов, которые ты по диагонали прочёл на Оберон-форуме? Вопрос риторический, можешь не отвечать.
То ты Absolutely agree! с тем, что программировать в ООП-стиле можно и без прямой поддержки ООП в языке
А как мое agree, на которое ты ссылаешься связано с данным заявлением? Журнализд-стайл?
то заставляешь меня показывать тебе как это может быть устроено на Си
Хочется проверить, знает ли человек то, о чем говорит. В твоем случае- не знает.
Alex Rider
01.10.2014, 23:31
А с одного Оберон-модуля получается такой оттранслированный сишный исходник, который не содержит в себе предпосылок для "умной линковки".
Другими словами, умный транслятор Оберона в C не может на выходе дать много маленьких файлов по одной функции или хотя бы файлов с cut-линиями, а дружное сообщество динамично развивающегося кросс-платформенного Оберона не собирается модифицировать транслятор для возможности сборки компакнтых программ под ретро-платформы?
Oleg N. Cher
01.10.2014, 23:52
А как мое agree, на которое ты ссылаешься связано с данным заявлением? Журнализд-стайл?Просто сопоставил два твои высказывания и нашёл в них одни придирки и самовыпячивание.
Хочется проверить, знает ли человек то, о чем говорит. В твоем случае- не знает.Но зато знает где это посмотреть. И уверен, что другие знают. Кому надо. А кому не надо - тому и не надо. И нечего ради таких напрягаться.
---------- Post added at 22:52 ---------- Previous post was at 22:51 ----------
Alex Rider, даже чуть не так. Умный транслятор Оберона в C силами одного дружного чела, динамично развивающего оный транслятор научился давать на выходе файлы с cut-линиями, но дело оказалось мудрёным, а сборка компактных программ под ретро-платформы - мало востребованной, посему подход и не получил должного развития. Хотя всё возможно.
Q-Master
02.10.2014, 22:27
Ну здрасьте, опять двадцать пять. А ты ответь что значит в твоём понимании "нормальные хедеры" и "с диким оверхедом"?
Это означает: не включаем в хедеры то, что там не нужно, не включаем в файлы исходного кода то что там ненужно. Не показываем конечному юзеру те ф-ции которые ему не нужны (скрываем реализацию служебных структур и частей кода).
Я и Витамин уже 100500 раз это писали.
Второй вопрос. Почему ты всё ещё не запускал ZXDev? Барьер вхождения?
Я не нашел ни слова документации в репозитории как это собрать. Все бинарники находящиеся там на моем powerpc G5 не запускаются т.к. собраны под и386.
Поясняю. Раз ZXDev - это Оберон-среда, то логично делать всё в Оберон-стиле. Писать библиотеки и модули на Обероне. Модуль на Обероне != одна сишная функция, помещённая в один маленький текстовый файл.
Манечка "разрезать библиотеку на кусочки по функциям" навязывается тебе инструментарием. Я это делаю утилитой и автоматически. Ты это делаешь ручками. Какой в этом смысл, объясни? А я тебе скажу. Ты так привык, и ничего пересматривать не хочешь. Ну и бог с тобой.
Вопрос без которого нельзя на вот то что ты написал ответить: ты каждый раз переписываешь библиотеки которые юзаются у тебя в zxdev? в смысле они каждый раз экспортируются по-новой в С-исходники и каждый раз собираются?
Если так то мой подход неверный. Если нет - не вижу проблемы доработать после экспорта напильником то что получилось для:
1) удобочитаемости и нормальной структурированности
2) исключению необходимости резать это все каждый раз каждую сборку.
3) скрытию системных и внутренних структур и ф-ций от конечного пользователя.
4) ускорению сборки в силу пп 2 и 3.
PS: Ответь мне, ты сам-то что пересмотрел в своих привычках за время треда?
А то, я смотрю, вместо ответа на простой вопрос ты начинаешь метать во всех подряд какашки и пытаться найти где там тебя и твой обожаемый мертвый язык так оскорбили и обидели...
Oleg N. Cher
03.10.2014, 00:16
Это означает: не включаем в хедеры то, что там не нужно, не включаем в файлы исходного кода то что там ненужно.Ага. Значит я, по-твоему, включаю в хедеры то, что мне не нужно и не включаю то, что нужно. Надо же. Сам понял чего сказал?
Но вообще хедеры генерируются автоматически с обероновских интерфейсов, так что я их даже не пишу ручками. Просто некоторые иногда дополнительно редактирую.
Не показываем конечному юзеру те ф-ции которые ему не нужны (скрываем реализацию служебных структур и частей кода).Всё правильно, ненужное скрываем. Это есть инкапсуляция.
Я и Витамин уже 100500 раз это писали.Вы не сказали ничего дельного по этому вопросу. Даже язык Си не требует помещения каждой функции в отдельный исходник. Ты же напираешь на необходимость это обязательно делать. Да, с SDCC по-другому пока и не сладить, но лучше бы ты задумался над тем как лучше сформулировать feature request разработчикам SDCC.
Ну что конкретно ты предлагаешь? И не дури мозг. Вовсе не "невключать то что ненужно включать то что нужно", а "помещать каждую функцию в отдельный файл". Ну хорошо. Будет в папке Lib не 44 файла, а 544. Легче кому от этого станет? Придётся имена всей этой тучи файлов хранить в мейк-файле (и постоянно его редактировать, дополняя новыми именами). Это что - удобно настолько, чтобы к этому стремиться? Нет, батенька. Это просто для тебя привычней. Ещё какие достоинства будут?
Я не нашел ни слова документации в репозитории как это собрать. Все бинарники находящиеся там на моем powerpc G5 не запускаются т.к. собраны под и386.Угу, угу. Витамин тоже в глаза никогда не видел ни винды, ни i386, представляясь линухойдом. Пока не прокололся, приаттачив презентацию ppt.
Не могу рассматривать такой ответ иначе как дешёвую рисовку.
Вопрос без которого нельзя на вот то что ты написал ответить: ты каждый раз переписываешь библиотеки которые юзаются у тебя в zxdev? в смысле они каждый раз экспортируются по-новой в С-исходники и каждый раз собираются?Да.
Но с некоторыми "но".
Библиотека, написанная на Обероне, собирается именно так, как ты сказал. Разрезание тоже работает, но с некоторыми ограничениями.
Поэтому исключительно для того чтобы юзать "умную линковку" используется полу-автоматическая генерация. Т.е. то, что нагенерил Ofront, ручками переносится в сишный исходник и редактируется для добавления "линий разреза". Иногда используется сишный препроцессор. Это для шика. Например, чтобы без перекомпиляции использовать разные опции работы библиотеки. С некоторыми ограничениями это можно юзать и из Оберона.
Наконец, чисто сишные библиотеки. Ну какой смысл резать их на сто кусочков? Чтобы подсластить жизнь утилите. Проклинаемый тобой оверхед - у тебя в голове, я уже писал, что авторазрезание даже на сто кусков занимает меньше секунды.
Ну и асмовые библиотеки. В сишной обёртке. Тоже нет никакого резона иметь каждую функцию в отдельном файле. Ну нету смысла в этом. Так делают, я снова повторюсь, только для того чтобы угодить плохому компилятору.
Если так то мой подход неверный. Если нет - не вижу проблемы доработать после экспорта напильником то что получилось для:
1) удобочитаемости и нормальной структурированностиДля этого у нас есть интерфейсы. Ты давно заглядывал в промежуточный код, сгенеренный любимым FreePascal?
Я ещё раз повторюсь. Интерфейсы генерируются автоматически. Чтобы у нас были доп. фишки (например, связанные с макропроцессором) - мы можем доработать напильником. Я так и делаю. Но не для всех библиотек, а только для некоторых.
2) исключению необходимости резать это все каждый раз каждую сборку.Пользователь не пересобирает библиотек. Как правило, это делает разработчик библиотек. Даже если пользователь пересобирает библиотеку - он делает это одним нажатием кнопки. Голова не болит. Разве что батничек подправить. Но в нём нету ста имён кусков файлов исходника.
3) скрытию системных и внутренних структур и ф-ций от конечного пользователя.Я повторюсь. Пользователь оперирует даже не хедерами. Интерфейсами. В них нет ничего лишнего. Но может быть много полезного, вплоть до комментариев, созданных с помощью автодокументирования (как в Javadoc).
4) ускорению сборки в силу пп 2 и 3.Т.е. из-за неприемлемости потратить полсекунды на работу утилиты разрезания ты предлагаешь вместо этого удесятерить количество файлов и усложнить процесс их сборки вынужденной необходимостью постоянно править имена в мейк-файле?
Слушай, у меня ужасное подозрение. Это твоя идея фикс. Грамотный разработчик зрит в корень. И уж точно усмотрит более приоритетные направления разработки. А их сотни. А что предлагаешь ты? Чепуху, вобщем.
PS: Ответь мне, ты сам-то что пересмотрел в своих привычках за время треда?Ещё более укрепился в своём почитании библейского принципа "око за око, зуб за зуб", и знаешь, правило верное - не подводит.
А то, я смотрю, вместо ответа на простой вопрос ты начинаешь метать во всех подряд какашки и пытаться найти где там тебя и твой обожаемый мертвый язык так оскорбили и обидели...А ты сталкивался с тем, что кто-то, рьяно рвущийся дать тебе совет, не вполне понимает что именно ты делаешь? А, соответственно, и не заслуживает более достойного ответа. А другие на меня и не в обиде. За это я спокоен. И благодарен за хорошие советы. С этим всё в порядке.
Я с этими скриптами и разбиением вожусь уже не один год. А, по-твоему, адекватный человек будет давать советы по усовершенствованию продукта, который он не то что юзает ежедневно, а вообще даже не смотрел?
Так, риторика.
Витамин тоже в глаза никогда не видел ни винды, ни i386, представляясь линухойдом. Пока не прокололся, приаттачив презентацию ppt.
Поставлю в подпись.
Oleg N. Cher
05.10.2014, 02:38
Alex Rider, чтобы ты понял как хреново обстоят дела с "умной линковкой" в сишном мире, нужно сказать, что в таком развивающемся компиляторе как Tiny C (tcc) её нету вообще. И разработчики не хотят добавлять эту фичу. Вообще не считая это чем-то важным. Более того, я не уверен, что она есть даже в MINGW. По крайней мере, люди пишут об этом. http://forum.ixbt.com/post.cgi?id=print:26:42363. В качестве эксперимента предлагаю это проверить. Я проверял. Правда, на старой версии MINGW. И действительно - fdata-sections, -ffunction-sections увеличивают размер библиотеки, а ключик --gc-sections не работает должным образом. И с fdata-sections, -ffunction-sections бинарь получается ещё жирнее, чем без них. И меня это не удивляет - килобайты давно уже никто не считает.
Так что это есть серьёзная проблема сразу для целой кучки сишных компиляторов, а вовсе не для одного. И пусть Q-Maйster не лезет сюда со своей вижл студией последней версии, а витамин со своим Clang. Мимо. Я говорю про MINGW, где ключики не срабатывают. Идите туда оба и пробейте эту фичу. Потом сделайте то же самое для SDCC. Тогда я вас похвалю. Может быть.
Мне кажется, самой большой проблемой здесь есть помещение static функций в библиотеку. Т.е. они должны видеться извне для подключения их к тем функциям, которые имеют на это право, но не должны видеться для других функций.
И я, разумеется, могу повлиять на эту ситуацию только очень ограниченным образом. Думаю, такой feature request будут отпинывать ногами куда подальше. Я говорю это не голословно, ибо уже делал такие реквесты.
Так что SDCC просто поддерживает старые добрые сишные традиции. "Режьте, братцы, режьте". Исходник на кусочки. Но спасибо хоть так, могло быть вообще никак.
---------- Post added at 01:38 ---------- Previous post was at 01:28 ----------
То есть получается, Alex, что ты заставляешь (или просишь) меня делать то, что не могут (или не хотят) сделать сообщества разработчиков сишных компиляторов, состоящие из десятка и более человек. Ну и где твоя гуманность? Хоть помощь предложи для приличия.
Впрочем, а как именно ты предлагаешь сделать "умную линковку"? Просто чтобы транслятор выдавал сразу кусочки, т.е. дублировал функциональность моей утилиты-резалки? А смысл в этом какой-то есть, кроме удовлетворения эго ку-майстера? Который даже не будет пользоваться этим, ибо у него powerpc G5.
Q-Master
05.10.2014, 19:24
Так что это есть серьёзная проблема сразу для целой кучки сишных компиляторов, а вовсе не для одного. И пусть Q-Maйster не лезет сюда со своей вижл студией последней версии, а витамин со своим Clang. Мимо. Я говорю про MINGW, где ключики не срабатывают. Идите туда оба и пробейте эту фичу. Потом сделайте то же самое для SDCC. Тогда я вас похвалю. Может быть.
Огорчу тебя еще раз. Я не юзаю вижуал студию и не юзал ни разу в жизни. Под твоим любимым мингв стандартно юзается gcc, а не tcc чего-бы ты ни говорил. В гцц такой проблемы практически нет. Заюзай таки самую новую версию мингв и скачай новый gcc под него. Насколько я вижу это 4.8.1. Там все есть.
Впрочем, а как именно ты предлагаешь сделать "умную линковку"? Просто чтобы транслятор выдавал сразу кусочки, т.е. дублировал функциональность моей утилиты-резалки? А смысл в этом какой-то есть, кроме удовлетворения эго ку-майстера? Который даже не будет пользоваться этим, ибо у него powerpc G5.
А ты собери мне под debian linux для powerpc процессоров и я попробую это. То что я даже вменяемой документации по сборке этого всего не нашел это уже как-бы показывает дружественность проекта.
PS: поскольку ты собираешь все каждый раз по-новой, то мой подход не катит. Хотя я и не очень понимаю в чем смысл пересборки и пересоздания сишных исходников каждый раз.
PPS: поскольку "дружественность" твоего восприятия любого совета просто ужасна - я не буду более тут ничего писать. надеюсь что проект с такой "поддержкой" таки выплывет.
Заюзай таки самую новую версию мингв и скачай новый gcc под него. Насколько я вижу это 4.8.1. Там все есть.
Юзаю 4.8.1 с http://sourceforge.net/projects/mingwbuilds/ - там эта опция влияет только на размер .pdb
Если дебужную инфу хранить в бинаре, то да, размер уменьшится.
Oleg N. Cher
06.10.2014, 12:58
это 4.8.1. Там все есть.А я не уверен, что там есть умная линковка для винды. Пробовать специально не буду, разве что когда-нибудь по какой-то оказии.
А ты собери мне под debian linux для powerpc процессоров и я попробую это. То что я даже вменяемой документации по сборке этого всего не нашел это уже как-бы показывает дружественность проекта.Его нельзя собрать для линукса. Это чисто виндоуз-проект. Что касается дружественности - я не господь бог и не могу сделать всё для всех, и чтобы всем понравилось. Это невозможно по определению.
PS: поскольку ты собираешь все каждый раз по-новой, то мой подход не катит. Хотя я и не очень понимаю в чем смысл пересборки и пересоздания сишных исходников каждый раз.А ты понимаешь смысл трансляции одного языка в другой?
PPS: поскольку "дружественность" твоего восприятия любого совета просто ужасна - я не буду более тут ничего писать. надеюсь что проект с такой "поддержкой" таки выплывет.Какие советы и какой тон - такая и реакция. ;)
Из здешних форумчан я благодарен Eltaron'у. Благодаря его совету в ZXDev появилась возможность передавать константные параметры внутрь функций в регистрах. И хотя такой возможности нет в SDCC - мы достигли этого с помощью препроцессора.
Ещё я благодарен Reobne. Благодаря его совету появилась возможность юзать inline-ассемблер прямо из Оберон-исходника. Причём без переделки транслятора - тоже с помощью макропроцессора.
Это хорошие советы. Твой же совет держать каждую функцию в отдельном файле - он, как бы помягче сказать, не очень. Ну да, твоя помойка будет принципиально отличаться от моей только удесятерённым количеством файлов. Причём ты даже не рискнёшь сказать, что это идеологически правильно и в духе Си. Просто сложил их так, чтобы не резать каждый раз.
Занимаясь Обероном я кое-что понял. А именно то, что проблему нужно решать в месте её возникновения. Любой другой подход будет навесным. А значит - нужно внедрять умную линковку в Си-компиляторы. Это самое правильное решение, которому не видится никакой другой разумной альтернативы. Ну будет выдавать Ofront кучу исходников. Т.е. будет делать то же самое, что и утилита. Смысл? Жизнь станет легче, что ли?
Если внедрить смартлинковку в Си-компилятор по каким-то причинам невозможно или затруднительно - иначе как утилитой, которая переформатирует исходник и приведёт его в вид, потребный для линковки, вопроса не решить. Да, моя утилита примитивна. Но что же делать? Давайте напишем вместе более умную утилиту. Давайте сформируем feature request в сообщество SDCC. Я не возражаю. Давайте что-нибудь сделаем в этом направлении.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot