Страницы

Поиск по вопросам

Показаны сообщения с ярлыком зависимости. Показать все сообщения
Показаны сообщения с ярлыком зависимости. Показать все сообщения

воскресенье, 12 января 2020 г.

Как подключить зависимость к проекту?

#c_sharp #зависимости #xamarin_studio


Есть простейший проект на C# (command-line application). Я хочу подключить к нему
сторонний проект в качестве модуля/зависимости. Я не буду менять код подключаемого
проекта, но хочу использовать его классы. Проект доступен в виде репозитория на GitHub.

Работаю на Xamarin Studio, Mono, OS X. Если это будет совершенно необходимо, могу
перейти на Visual Studio на Windows.

Пока что вижу следующие пути решения:


Найти аналог Maven для C#. (На Java я бы шел именно этим путем). Пока что поиск не
дал никакого лидирующего решения. Предлагаются разные варианты, но они то непопулярны,
то вовсе поддержка прекращена.
Подключать submodule в Git и сам проект как-то импортировать в Xamarin Studio.


Как вообще принято подключать зависимости в .net?

UPD: Похоже, что решение называется NuGet. В качестве ответа хотелось бы пошаговую
инструкцию по подключению зависимости.
    


Ответы

Ответ 1



В Xamarin Studio есть интеграция с NuGet, начиная с 3-й версии Xamarin. Открываете окно Solution Right Click по проекту, выбираете Add / Add Packages. В диалоге ищете нужный вам пакет, нажимаете Add. В официальном блоге есть пошаговая инструкция с картинками.

суббота, 11 января 2020 г.

Разрешение зависимостей для орграфа с циклами

#графы #зависимости #dependencies #компиляция


Балуюсь, хочу сделать транслятор из BNF в код-грамматику для LEPL. Парсер написал,
код для отдельных правил генерируется, но дальше подзастрял с порядком правил.

Есть набор правил, ссылающихся друг на друга. Зависимости можно просто представить
в виде орграфа, в котором есть циклы:



Нужно разрешить зависимости относительно заданной вершины, получив список, в котором
следует записывать правила так, чтобы последующие правила уже «видели» все требуемые
им предыдущие. Если возникает цикл — нужно перед первым употреблением поместить «предварительную
декларацию.» Т.е., для примера графа выше, если, упрощая, считать, что вершины содержат
просто строки, получить что-то в духе:

>>> deps_dict = {
...    "A": {"B", "C"},
...    "B": {"D", "E"},
...    "C": {"A", "E"},
...    "E": {"E", "D"}
... }
>>> resolve_deps(deps_dict, "A")
[
    "D"              # {}
    Predeclare("E"), # ref'd by {E, B}
    "E"              # {D, E}
    "B"              # {D, E}
    Predeclare("A"), # ref'd by {C}
    "C"              # {A, E}
    "A"              # {B, C}
]


(То, что это не единственный вариант удовлетворяющего условиям результата — понятно.)

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

Если бы циклов не было — все было бы, вроде как, понятно — про топологическую сортировку
я нашел и почитал. Но как справиться с циклами — честно говоря, пока не соображу.
    


Ответы

Ответ 1



Поскольку БНФ оперирует контекстно-свободными грамматиками, то самое простое - это использовать соответствующий раздел теории синтаксического анализа. Самое неприятное, что может быть в произвольно взятой КС-грамматике G - это левая рекурсия, которая, нестрого говоря, делает грамматику G недетерминированной. При этом шаги алгоритма избавления от левой рекурсии включают в себя избавление от циклов. Поскольку вы, судя по всему, пытаетесь достичь детерминированности соответствующей грамматики, то лично я рекомендовал бы сразу же заимплементировать алгоритм избавления от левой рекурсии. Простое описание подхода избавления от левой рекурсии можно найти здесь, более же обзорная публикация по разным алгоритмам избавления от левой рекурсии расположена тут. Если вы действительно знаете, что делаете и хотите только избавиться от циклов, то воспользуйтесь только шагами (1) и (2) из публикации Eliminating left-recursion: three steps. Из дополнительных референсов могу порекомендовать пост Эрика Липперта по поводу CFG и циклов в них вообще, а также набор хороших презентаций по теории формальных языков.

четверг, 19 декабря 2019 г.

Как разрешить циклические зависимости в Делфи?

#delphi #ооп #delphi_xe5 #зависимости


Допустим у нас есть 2 класса, расположенных в разных юнитах:


TMaster - хозяин собаки, который должен о ней знать
TDog - собака, которая должна знать о своем хозяине


Unit_Master:

uses Unit_Dog;
type TMaster = class
public
  Dog: TDog;
end;


Unit_Dog:

uses Unit_Master;
type TDog = class
public
  Master: TMaster;
end;


Использование таких прямых ссылок между классами очень облегчило бы жизнь. К сожалению,
Delphi не может скомпилировать такой код из-за циклической зависимости между юнитами.

Как грамотно разрулить циклическую зависимость и скомпилировать подобный код, какие
есть способы?
    


Ответы

Ответ 1



Можно использовать интерфейсы и в классах хранить ссылки на них, а не на объекты: unit EntityInterfaces type IMaster = interface; IDog = interface; IMaster = interface ['{8417E5A8-02FE-4A83-BD0C-F69E79492796}'] function GetDog: IDog; procedure SetDog(const ADog: IDog); property Dog: IDog read GetDog write SetDog; end; IDog = interface ['{9B501AD7-BD77-46AC-BC08-545433EC5FFE}'] function GetMaster: IMaster; procedure SetMaster(const AMaster: IMaster); property Master: IMaster read GetMaster write SetMaster; end; Сами классы в этом случае объявляются так: TMaster = class(TInterfacedObject, IMaster) private [Weak] FDog: IDog; function GetDog: IDog; procedure SetDog(const ADog: IDog); end; TDog = class(TInterfacedObject, IDog) private [Weak] FMaster: IMaster; function GetMaster: IMaster; procedure SetMaster(const AMaster: IMaster); end; И работа ведется уже с интерфейсами: procedure TForm11.btn1Click(Sender: TObject); var Master: IMaster; Dog: IDog; begin Master := TMaster.Create; Dog := TDog.Create; Master.Dog := Dog; Dog.Master := Master; end; // на выходе из метода Master и Dog будут автоматически удалены, // поскольку их "циклические ссылки" друг на друга имеют атрибут Weak // без использования слабых ссылок возникла бы утечка памяти. Недостатки способа: необходимость дважды описывать методы - в интерфейсе и непосредственно в реализации. автоудаление объекта при доведении счетчика ссылок до нуля будет непривычно тем, кто не работал с интерфейсами. Для ликвидации последнего недостатка можно сделать собственную реализацию IUnknown и наследовать свои классы не от TInterfacedObject, а от TNoReferenceObject : type TNoReferenceObject = class(TObject, IInterface) { IInterface } function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; end; { TNoReferenceObject } function TNoReferenceObject.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then Result := 0 else Result := E_NOINTERFACE; end; function TNoReferenceObject._AddRef: Integer; begin Result := -1; end; function TNoReferenceObject._Release: Integer; begin Result := -1; end; Подсчет ссылок для всех наследников TNoReferenceObject не будет действовать и все созданные экземпляры нужно будет удалять вручную, как и обычные объекты: procedure TForm11.btn1Click(Sender: TObject); var Master: IMaster; Dog: IDog; begin Master := TMaster.Create; Dog := TDog.Create; try Master.Dog := Dog; Dog.Master := Master; finally TObject(Master).Free; TObject(Dog).Free; end; end;

Ответ 2



Вариант №1 Объединить оба класса в 1 файл и воспользоваться forward declaration: Unit: type TDog = class; // т.н. forward declaration TMaster = class public Dog: TDog; end; TDog = class public Master: TMaster; end; Минусы очевидны - получаем один огроменный файл с кучей кода.

Ответ 3



Вариант №2 Создать общего предка, с общими методами: Unit_Entity: type TEntity = class end; Unit_Dog: uses Unit_Entity; type TMaster = class(TEntity) public Dog: TEntity; end; Unit_Dog: uses Unit_Entity; type TDog = class(TEntity) public Master: TEntity; end; Минусы в том, что весь код специфический для каждого класса по прежнему остается в каждом классе и недоступен без дополнительных решений.

Ответ 4



Вариант №3 Использовать общего предка и приводить типы при обращении к объектам: Unit_Master: type TMaster = class public Dog: TObject; end; implementation uses Unit_Dog; .. TDog(Dog).Bark; Unit_Dog: type TDog = class public Master: TObject; end; implementation uses Unit_Master; .. TMaster(Master).Yell; Минусы в том, что при каждом обращении нам придется приводить объект к определенному классу. При большом количестве обращений, это загромождает код.

Ответ 5



Вариант №4 Использовать помощники классов. (Способ через private официально перестал работать с Delphi Seattle (но есть пути как обойти: https://stackoverflow.com/questions/37351215) и, вероятно, можно будет перейти на protected) Unit_Helper: uses Unit_Master, Unit_Dog; type TMasterHelper = class helper for TMaster private function GetDog: TDog; procedure SetDog(aObject: TDog); public property Dog: TDog read GetDog write SetDog; end; TDogHelper = class helper for TDog private function GetMaster: TMaster; procedure SetMaster(aObject: TMaster); public property Master: TMaster read GetMaster write SetMaster; end; function TMasterHelper.GetDog: TDog; begin Result := fDog; end; Unit_Master: type TMaster = class protected fDog: TObject; end; uses Unit_Helper; .. Dog.Bark; Unit_Dog: type TDog = class protected fMaster: TObject; end; uses Unit_Helper; .. Master.Yell; Минусы в том, что у класса может быть максимум 1 помощник, следовательно воспользоваться этим трюком можно только 1 раз.

вторник, 10 декабря 2019 г.

Игнорирование ненужного пакета-зависимости при обновлении

#linux #archlinux #обновление #зависимости


TL;DR Arch Linux, pacman, два пакета конфликтуют, первый нужен, а второй является
зависимостью нужного meta-пакета. Удалил второй пакет, но при обновлении pacman выдаёт
ошибку, как убрать её?



В arch linux есть пакеты openbabel и babel-cli, которые конфликтуют. Пакет openbabel
является зависимостью пакета kalzium, тот является зависимостью пакета kde-meta-kdeedu,
который является зависимостью пакета kde-applications-meta. Вот схема зависимости:

kde-applications-meta
|
v
kde-meta-kdeedu
|
v
kalzium
|
v
openbabel


Пакет kde-applications-meta скорее всего полезный, так что его удалять нельзя. Пакет
openbabel мне не нужен (там что-то, связанное с химией), поэтому при установки пакета
babel-cli я удалил пакет openbabel, выполнив pacman -Rdd openbabel. Однако теперь при
обновлении системы (pacman -Syu) pacman пытается заново установить openbabel (как зависимость
kalzium), и у него, конечно, не получается:

разрешение зависимостей...
проверка конфликтов...
ошибка: обнаружен неразрешимый конфликт пакетов
ошибка: не удалось подготовить транзакцию (конфликтующие зависимости)
:: 'babel-cli' и 'openbabel' конфликтуют


Какой наиболее правильный способ сказать pacman'у, чтобы он при обновлении kalzium
не пытался установить openbabel?



В комментариях советуют добавить пакет openbabel к игнорируем с помощью строки IgnorePkg
в файле /etc/pacman.conf. Совет хороший, но тогда каждый раз при обновлении pacman
будет спрашивать, примерно так:

разрешение зависимостей...
предупреждение: пропуск пакета openbabel-2.4.1-4
предупреждение: не удалось разрешить "openbabel", зависимость "kalzium"
:: Этот пакет не может быть обновлен из-за неразрешимых зависимостей:
      kalzium

:: Вы уверены что хотите пропустить этот пакет при обновлении? [y/N] 


Как тогда убрать этот вопрос?
    


Ответы

Ответ 1



Создай виртуальный пакет openbabel-fake, который будет предоставлять альтернативу openbabel. Не прокатило из-за явного конфликта. Когда-нибудь мейнтейнеры должны с этим разобраться. А пока: extra/kalzium 17.08.1-1 (kde-applications kdeedu) Periodic Table of Elements Кажется не очень нужным пакетом. Заменим его, тогда мета не будет ругаться. Создай виртуальный пакет kalzium-fake, который будет предоставлять альтернативу kalzium Пример aur/akonadi-fake. Если только один раз поставить, то можно прямо на месте исправить PKGBUILD. Создавай свой пакет если ставить не один раз. А полный текст пакета будет такой: # Maintainer: Your Name pkgname=kalzium-fake pkgver=1000.0.0 pkgrel=3 pkgdesc="A fake empty kalzium package for those who don't want openbabel installed on their system" arch=('any') url="https://aur.archlinux.org/packages/${pkgname}/" license=('GPL') provides=('kalzium') replaces=('kalzium') package() { true }

среда, 12 июня 2019 г.

Зависимости от библиотеки

Всем Здрасте, Есть задача: прилинковать С++ библиотеку без лишних зависимостей, то есть:
Есть библиотека lib1 эта библитека зависит от библиотеки lib2. Есть проект proj1 и proj2. Они оба зависят от и используют lib1
Но proj1 использует функционал lib2 соответственно зависимость от этой библиотеки ему нужна. А proj2 не использует функционал lib2 соответственно зависимость от этой библиотеки ему не нужна
Как прилинковать lib1 в proj2 и исключить зависимости от lib2?


Ответ

Библиотека - это просто архив объектных файлов. В "традиционном" режиме линковка библиотек делается с точностью до индивидуальных объектных файлов. Если при линковке lib1 в proj2 удастся аккуратно "выхватить" из lib1 только те объектные файлы, которые не ссылаются на символы из lib2, то линковать lib2 в proj2 не понадобится вообще. Задача решена. Для этого обычно нужно, чтобы объектные файлы в lib1 были продуманно/аккуратно организованы и довольно тонко гранулированы.
Если же какие-то символы из lib2 все таки притянутся в proj2, то ничего не поделаешь: придется либо линковать lib2 в proj2, либо писать "заглушки" для этих символов.

вторник, 26 марта 2019 г.

Как разрешить циклические зависимости в Делфи?

Допустим у нас есть 2 класса, расположенных в разных юнитах:
TMaster - хозяин собаки, который должен о ней знать TDog - собака, которая должна знать о своем хозяине
Unit_Master:
uses Unit_Dog; type TMaster = class public Dog: TDog; end;
Unit_Dog:
uses Unit_Master; type TDog = class public Master: TMaster; end;
Использование таких прямых ссылок между классами очень облегчило бы жизнь. К сожалению, Delphi не может скомпилировать такой код из-за циклической зависимости между юнитами.
Как грамотно разрулить циклическую зависимость и скомпилировать подобный код, какие есть способы?


Ответ

Вариант №4
Использовать помощники классов.
(Способ через private официально перестал работать с Delphi Seattle (но есть пути как обойти: https://stackoverflow.com/questions/37351215) и, вероятно, можно будет перейти на protected)
Unit_Helper:
uses Unit_Master, Unit_Dog; type TMasterHelper = class helper for TMaster private function GetDog: TDog; procedure SetDog(aObject: TDog); public property Dog: TDog read GetDog write SetDog; end;
TDogHelper = class helper for TDog private function GetMaster: TMaster; procedure SetMaster(aObject: TMaster); public property Master: TMaster read GetMaster write SetMaster; end;
function TMasterHelper.GetDog: TDog; begin Result := fDog; end;
Unit_Master:
type TMaster = class protected fDog: TObject; end; uses Unit_Helper; .. Dog.Bark;
Unit_Dog:
type TDog = class protected fMaster: TObject; end; uses Unit_Helper; .. Master.Yell;
Минусы в том, что у класса может быть максимум 1 помощник, следовательно воспользоваться этим трюком можно только 1 раз.

четверг, 28 февраля 2019 г.

Разрешение зависимостей для орграфа с циклами

Балуюсь, хочу сделать транслятор из BNF в код-грамматику для LEPL. Парсер написал, код для отдельных правил генерируется, но дальше подзастрял с порядком правил.
Есть набор правил, ссылающихся друг на друга. Зависимости можно просто представить в виде орграфа, в котором есть циклы:

Нужно разрешить зависимости относительно заданной вершины, получив список, в котором следует записывать правила так, чтобы последующие правила уже «видели» все требуемые им предыдущие. Если возникает цикл — нужно перед первым употреблением поместить «предварительную декларацию.» Т.е., для примера графа выше, если, упрощая, считать, что вершины содержат просто строки, получить что-то в духе:
>>> deps_dict = { ... "A": {"B", "C"}, ... "B": {"D", "E"}, ... "C": {"A", "E"}, ... "E": {"E", "D"} ... } >>> resolve_deps(deps_dict, "A") [ "D" # {} Predeclare("E"), # ref'd by {E, B} "E" # {D, E} "B" # {D, E} Predeclare("A"), # ref'd by {C} "C" # {A, E} "A" # {B, C} ]
(То, что это не единственный вариант удовлетворяющего условиям результата — понятно.)
Положение в списке предварительных деклараций не очень важно — в худшем случае, можно их вытащить наверх, хотя лично мне хочется размещать их не раньше самого необходимого (т.е. перед первой отсылкой).
Если бы циклов не было — все было бы, вроде как, понятно — про топологическую сортировку я нашел и почитал. Но как справиться с циклами — честно говоря, пока не соображу.


Ответ

Поскольку БНФ оперирует контекстно-свободными грамматиками, то самое простое - это использовать соответствующий раздел теории синтаксического анализа. Самое неприятное, что может быть в произвольно взятой КС-грамматике G - это левая рекурсия, которая, нестрого говоря, делает грамматику G недетерминированной.
При этом шаги алгоритма избавления от левой рекурсии включают в себя избавление от циклов. Поскольку вы, судя по всему, пытаетесь достичь детерминированности соответствующей грамматики, то лично я рекомендовал бы сразу же заимплементировать алгоритм избавления от левой рекурсии.
Простое описание подхода избавления от левой рекурсии можно найти здесь, более же обзорная публикация по разным алгоритмам избавления от левой рекурсии расположена тут.
Если вы действительно знаете, что делаете и хотите только избавиться от циклов, то воспользуйтесь только шагами (1) и (2) из публикации Eliminating left-recursion: three steps
Из дополнительных референсов могу порекомендовать пост Эрика Липперта по поводу CFG и циклов в них вообще, а также набор хороших презентаций по теории формальных языков.