Каков ваш опыт работы с нерекурсивными программами? [закрыто]

Заменить это:

StreamWriter file2 = new StreamWriter("c:/file.txt");

с помощью этого:

StreamWriter file2 = new StreamWriter("c:/file.txt", true);

true указывает, что он добавляет текст.

61
задан Jon Ericson 22 May 2019 в 16:08
поделиться

6 ответов

Мы используем нерекурсивный GNU, Делают систему в компании, на которую я работаю. Это основано на статье Miller's, и особенно "Нерекурсивная реализация делает" ссылку, которую Вы дали. Нам удалось совершенствовать код Бергена в систему, где нет никакого шаблона вообще в make-файлах подкаталога. В общем и целом это хорошо работает и намного лучше, чем наша предыдущая система (рекурсивная вещь, сделанная с GNU, Автоделают).

Мы поддерживаем все "главные" операционные системы там (коммерчески): AIX, HP-UX, Linux, OS X, Солярис, Windows, даже мейнфрейм AS/400. Мы компилируем тот же код для всех этих систем с зависимыми частями платформы, изолированными в библиотеки.

существует больше чем два миллиона строк кода C в нашем дереве приблизительно в 2 000 подкаталогов и 20 000 файлов. Мы серьезно рассмотрели использование SCons, но просто не могли заставить его работать достаточно быстро. В более медленных системах Python использовал бы несколько дюжин секунд, просто анализирующих в файлах SCons, где GNU Делает, выполнил в том же самом приблизительно одна секунда. Это было приблизительно три года назад, таким образом, вещи, возможно, изменились с тех пор. Обратите внимание, что мы обычно сохраняем исходный код на NFS/CIFS, совместно используют и создают тот же код нескольких платформ. Это означает, что это еще медленнее для инструмента сборки для сканирования исходного дерева для изменений.

Наш нерекурсивный GNU Делает систему, не без проблем. Вот некоторые самые большие препятствия, с которыми можно ожидать сталкиваться:

  • Создание его портативный, особенно к Windows, является большой работой.
  • , В то время как GNU Делают, почти применимый язык функционального программирования, это не подходит для программирования в большом. В частности, нет никаких пространств имен, модулей или чего-либо как этот, чтобы помочь Вам изолировать части друг от друга. Это может вызвать проблемы, хотя не так, как Вы могли бы думать.

главные победы над нашей старой рекурсивной системой make-файла:

  • Это быстро . Требуется приблизительно две секунды, чтобы проверить все дерево (2k каталоги, 20k файлы) и или решить, что это актуально, или начните компилировать. Старая рекурсивная вещь заняла бы больше чем минуту, чтобы ничего не сделать.
  • Это обрабатывает зависимости правильно. Наша старая система полагалась на подкаталоги порядка, были созданы и т.д. Точно так же, как Вы будете ожидать от того, чтобы читать газету Miller's, рассматривая целое дерево, поскольку единственный объект является действительно правильным способом заняться этой проблемой.
  • Это портативно ко всем нашим поддерживаемым системам после всей тяжелой работы, которую мы вылили в него. Это довольно прохладно.
  • система абстракции позволяет нам писать очень краткие make-файлы. Типичный подкаталог, который определяет просто библиотеку, является всего двумя строками. Одна строка дает название библиотеки и других списков библиотеки, от которых этот зависит.

Относительно последнего объекта в вышеупомянутом списке. Мы закончили тем, что реализовали своего рода средство макрорасширения в системе сборки. Make-файлы подкаталога перечисляют программы, подкаталоги, библиотеки, и другие общие вещи в переменных как ПРОГРАММЫ, SUBDIRS, ОСВОБОЖДАЮТ. Затем каждый из них расширен в "реальный" GNU, Делают правила. Это позволяет нам избегать большой части проблем пространства имен. Например, в нашей системе хорошо иметь несколько исходных файлов с тем же именем, без проблем там.

В любом случае, это закончило тем, что было большой работой. Если можно получить SCons или подобную работу для кода, я был бы совет Вы смотреть на это сначала.

52
ответ дан Talespin_Kit 22 May 2019 в 16:08
поделиться
  • 1
    Та страница почти заставила меня рвать – BlueRaja - Danny Pflughoeft 21 January 2010 в 03:31

Я знаю о по крайней мере одном крупномасштабном проекте ( КОРЕНЬ ), который рекламирует использование [powerpoint ссылка] , механизм, описанный в Рекурсивном, Делает Продуманными Вредный. Платформа превышает миллион строк кода и компиляций вполне энергично.

<час>

И, конечно, все великоватые проекты я работаю с тем , делают , используют рекурсивный, делают, мучительно не спешат компилировать.:: вздох::

7
ответ дан dmckee 22 May 2019 в 16:08
поделиться

Позвольте мне подчеркнуть один аргумент статьи Miller's: Когда Вы начинаете вручную разрешать отношения зависимости между различными модулями и приходиться нелегко для обеспечения порядка сборки, Вы эффективно повторно реализуете логику, которую система сборки была сделана решить во-первых. Построение, надежное рекурсивный, делает системы сборки, очень твердо. Реальные проекты имеют много взаимозависимых частей, порядок сборки которых нетривиален для выяснения и таким образом, эту задачу нужно оставить системе сборки. Однако это может только разрешить, что проблема, если это имеет глобальное знание системы.

, Кроме того, рекурсивный делают системы сборки, являются склонными для разваливаний при создании одновременно на нескольких процессорах/ядрах. В то время как эти системы сборки, может казаться, работают надежно над единственным процессором, много недостающих зависимостей идут необнаруженные, пока Вы не начинаете разрабатывать свой проект параллельно. Я работал с рекурсивным, делают систему сборки, которая продолжила работать до четырех процессоров, но внезапно отказала на машине с двумя квадратическими ядрами. Затем я сталкивался с другой проблемой: Эти проблемы параллелизма почти невозможны для отладки, и я закончил тем, что рисовал блок-схему целой системы для выяснения то, что пошло не так, как надо.

Для возвращения к вопросу мне трудно думать о серьезных основаниях, почему каждый хочет использовать рекурсивный, делают. Производительность во время выполнения нерекурсивного GNU Делает системы сборки, твердо биться и, вполне обратное, многие рекурсивные заставляют системы иметь серьезные проблемы производительности (слабая параллельная поддержка сборки является снова частью проблемы). Существует бумага , в котором я оценил (рекурсивное) определенное, Делают систему сборки и сравнил его с портом SCons. Результаты проверки производительности не являются представительными, потому что система сборки была очень нестандартна, но в данном случае порт SCons был на самом деле быстрее.

Нижняя строка: Если Вы действительно хотите использовать, Делают для управления сборками программного обеспечения, пойдите для нерекурсивного, Делают, потому что это делает жизнь намного легче в конечном счете. Лично, я использовал бы SCons по причинам удобства использования (или Грабли - в основном любая система сборки с помощью современного языка сценариев и который имеет неявную поддержку зависимости).

18
ответ дан Pankrat 22 May 2019 в 16:08
поделиться

Я предпринял нерешительную попытку своего предыдущего задания при создании системы сборки (на основе GNU, делают), абсолютно нерекурсивный, но я столкнулся со многими проблемами:

  • артефактам (т.е. библиотеки и созданные исполняемые файлы) распространяли их источники по многим каталогам, полагаясь vpath для нахождения их
  • , Несколько исходных файлов с тем же именем существовали в различных каталогах
  • , Несколько исходных файлов были совместно использованы артефактами, часто компилируемыми с различными флагами компилятора
  • , Различные артефакты часто имели различные флаги компилятора, настройки оптимизации, и т.д.

, Одна функция GNU делает, который упрощает нерекурсивное использование, целевые значения переменных :

foo: FOO=banana
bar: FOO=orange

Это означает, что при создании целевого "нечто", $ (НЕЧТО) расширится до "банана", но при создании целевой "панели", $ (НЕЧТО) расширится до "оранжевого".

Одно ограничение этого - то, что не возможно иметь целевые определения VPATH, т.е. нет никакого способа исключительно определить VPATH индивидуально для каждой цели. Это было необходимо в нашем случае для нахождения корректных исходных файлов.

основная недостающая возможность GNU делает необходимыми для поддержки нерекурсивности, то, что этому недостает пространства имен . Целевые переменные могут ограниченным способом использоваться для "моделирования" пространств имен, но в чем Вы действительно нуждались бы, должен смочь включать Make-файл в подкаталог с помощью локального объема.

РЕДАКТИРОВАНИЕ: Другой очень полезный (и часто недогруженный) функция GNU делает в этом контексте, средства макрорасширения (см. оценка функция, например). Это очень полезно, когда у Вас есть несколько целей, которые имеют подобные правила/цели, но отличаются способами, которых нельзя выразить с помощью регулярного GNU, делают синтаксис.

10
ответ дан JesperE 22 May 2019 в 16:08
поделиться

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

В настоящее время я работаю над небольшим исследовательским проектом, в котором экспериментирую с непрерывной интеграцией; автоматический модульный тест на ПК, а затем запуск системного теста на (встроенной) цели. Это нетривиально для make, и я искал хорошее решение. Обнаружив, что make по-прежнему является хорошим выбором для переносимых мультиплатформенных сборок, я наконец нашел хорошую отправную точку в http://code.google.com/p/nonrec-make

. Это было настоящим облегчением. Теперь мои make-файлы

  • очень просто изменить (даже с ограниченными знаниями make)
  • быстро скомпилировать
  • , полностью проверяя (.
9
ответ дан 24 November 2019 в 17:11
поделиться

После прочтения статьи RMCH я поставил перед собой цель написать правильный нерекурсивный Makefile для небольшого проекта, над которым я работал в то время. После того, как я закончил, я понял, что должно быть возможно создать общую «структуру» Makefile, которую можно использовать, чтобы очень просто и кратко сказать make, какие конечные цели вы хотите создать, какие они цели (например, библиотеки или исполняемые файлы ) и какие исходные файлы должны быть скомпилированы для их создания.

После нескольких итераций я в конечном итоге создал именно это: единый шаблонный Makefile, состоящий примерно из 150 строк синтаксиса GNU Make, который никогда не нуждается в модификации - он просто работает для любого типа проекта, в котором я хочу его использовать, и достаточно гибок, чтобы создавать несколько целей разных типов с достаточной степенью детализации, чтобы указать точные флаги компиляции для каждого исходного файла (если я хочу) и точные флаги компоновщика для каждого исполняемого файла. Для каждого проекта все, что мне нужно сделать, это предоставить ему небольшие отдельные файлы Makefile, которые содержат биты, подобные этому:

TARGET := foo

TGT_LDLIBS := -lbar

SOURCES := foo.c baz.cpp

SRC_CFLAGS   := -std=c99
SRC_CXXFLAGS := -fstrict-aliasing
SRC_INCDIRS  := inc /usr/local/include/bar

Makefile проекта, подобный приведенному выше, будет делать именно то, что вы ожидаете: создать исполняемый файл с именем "foo" , компилируя foo.c (с CFLAGS = -std = c99) и baz.cpp (с CXXFLAGS = -fstrict-aliasing) и добавляя "./inc" и "/ usr / local / include / bar" в #include путь поиска с окончательной компоновкой, включая библиотеку "libbar". Он также заметил бы, что существует исходный файл C ++ и известно, что нужно использовать компоновщик C ++ вместо компоновщика C. Фреймворк позволяет мне указать намного больше, чем показано здесь в этом простом примере.

Шаблонный файл Makefile выполняет все построение правил и автоматическое создание зависимостей, необходимых для построения указанных целей. Все файлы, созданные при сборке, помещаются в отдельную иерархию выходных каталогов, поэтому они не смешиваются с исходными файлами (и это делается без использования VPATH, поэтому нет проблем с наличием нескольких исходных файлов с одинаковыми именами).

Я теперь (повторно) использовал тот же Makefile по крайней мере в двух десятках различных проектов, над которыми я работал. Что мне больше всего нравится в этой системе (помимо того, насколько просто создать правильный Makefile для любого нового проекта):

  • Это быстро . Он может практически мгновенно определить, что что-то устарело.
  • 100% надежные зависимости. Нет никакой вероятности, что параллельная сборка загадочным образом сломается, и она всегда строит ровно минимум, необходимый для обновления всего.
  • Мне никогда не придется переписывать снова полный make-файл: D

Наконец, я бы просто упомянул, что с проблемами, присущими рекурсивному make, я не думаю, что у меня было бы возможность осуществить это. Я, вероятно, был бы обречен переписывать некорректные make-файлы снова и снова, тщетно пытаясь создать тот, который действительно работал бы должным образом.

  • Мне никогда не понадобится заново переписывать полный make-файл: D
  • Наконец, я просто упомянул, что с проблемами, присущими рекурсивному make, я не думаю, что это было бы возможно для меня, чтобы осуществить это. Я, вероятно, был бы обречен переписывать некорректные make-файлы снова и снова, тщетно пытаясь создать тот, который действительно работал бы должным образом.

  • Мне никогда не потребуется заново переписывать полный make-файл: D
  • Наконец, я просто упомянул, что с проблемами, присущими рекурсивному make, я не думаю, что это было бы возможно для меня, чтобы осуществить это. Я, вероятно, был бы обречен переписывать некорректные make-файлы снова и снова, тщетно пытаясь создать тот, который действительно работал бы должным образом.

    29
    ответ дан 24 November 2019 в 17:11
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: