Dystrybucja programów#

Kiedy chcesz dystrybuować swój program, istnieje wiele opcji, z których możesz wybrać:

  1. Dystrybucja całego kodu źródłowego

  2. Dystrybucja gotowego wykonywalnego programu

  3. Dystrybucja statycznych lub dynamicznych bibliotek, których mogą używać ludzie

Opcja 1: Dystrybucja całego kodu źródłowego

Jak dotąd najprostsze rozwiązanie - dla ciebie jako programisty: pozostawiasz kompilację programu na ich własnej maszynie użytkownikom. Niestety, oznacza to również, że musisz mieć przyjazny dla użytkowników system kompilacji oraz będą oni musieli mieć dostęp do odpowiednich kompilatorów. Aby przeczytać więcej o systemach kompilacji: zobacz poprzednią sekcję.

Opcja 2: Dystrybucja gotowego wykonywalnego programu

Gotowy wykonywalny program, który nie musi być zmieniany, oprócz danych wejściowych, i tak będzie musiał zawierać różne biblioteki środowiska wykonawczego oraz będzie specyficzny dla systemu operacyjnego/środowiska dla którego został stworzony.

Zestaw bibliotek środowiska wykonawczego różni się w zależności od systemu operacyjnego i wersji kompilatora. Dla darmowych dostępnych kompilatorów, takich jak gfortran, najłatwiejszym rozwiązaniem jest zasugerowanie użytkownikom, aby zainstalowali ten kompilator w ich systemie. W przypadku Windowsa: środowisko Cygwin może być wymagane.

Alternatywnie, możesz dołączyć kopie bibliotek środowiska wykonawczego razem z twoim programem. Umieść je w folderze, w którym mogą być znalezione w czasie uruchomienia programu.

Uwaga: W systemie Windows Intel Fortran jest dostarczany z zestawem bibliotek redystrybuowalnych. Będą one musiały zostać udostępnione.

Ogólnie mówiąc: używaj narzędzi takich jak „ldd” lub „dependency walker”, aby dowiedzieć się jakie biblioteki są wymagane oraz zapoznaj się z dokumentacją kompilatora.

Jeśli twój program pozwala na dostosowywanie go do własnych potrzeb, rozważ użycie dynamicznych bibliotek w tym celu. Więcej o tym możesz przeczytać poniżej.

Opcja 3: Dystrybucja statycznych lub dynamicznych bibliotek, których mogą używać ludzie

Ta opcja to połączenie dwóch pierwszych opcji. Jest to obciążenie dla użytkowników, ponieważ muszą oni stworzyć program główny, który będzie wywoływał twoje procedury w odpowiedni sposób, jednak nie muszą oni wiedzieć wiele o używanym procesie kompilacji. Jednak będziesz musiał radzić sobie z bibliotekami środowiska wykonawczego.

Jeśli wybierzesz tę opcję, oprócz skompilowanych bibliotek będziesz musiał dołączyć również pliki pośrednie modułu. Te pliki są specyficzne dla danego kompilatora, ale tak samo jest ze statycznymi bibliotekami, które tworzysz.

Dystrybucjaprogramu tabelarycznego#

Jak pokazano powyżej, program tabelaryczny może zostać stworzony za pomocą funkcji stworzonej przez użytkownika w bibliotece dynamicznej. To pozwala ci na:

  • Dostarczyć plik wykonywalny (razem z odpowienimi bibliotekami środowiska wykonawczego)

  • Udostępnić szkielet modułu, taki jak:

module user_functions
    implicit none
contains

real function f( x )
!DEC$ ATTRIBUTES DLLEXPORT :: f
    real, intent(in) :: x

    ! your function body goes here

end function f

end module user_functions
  • Zapewnić podstawowy skrypt kompilacji za pomocą komendy takiej jak:

gfortran -o functions.dll functions.f90 -shared

lub:

ifort -exe:functions.dll functions.f90 -dll

Tak jak zaznaczono już wcześniej, nie możesz kontrolować czy użytkownik wykonał wszystko poprawnie - dowolna biblioteka współdzielona (DLL) „functions.dll” z funkcją f zostanie zaakceptowana, jednak niekoniecznie doprowadzi do jej poprawnego uruchomienia.

Alternatywnym rozwiązaniem byłoby zamienienie głównego programu na podprogram i przekazanie funkcji jako argument:

module tabulation
    implicit none
contains

subroutine tabulate( f )
    interface
        real function f( x )
            real, intent(in) :: x
        end function f
    end interface

    ! your implementation goes here

end subroutine tabulate

end module tabulation

Następnie dostarcz szkielet programu głównego:

program tabulate_f
    use tabulation

    call tabulate( func1 )

contains

real function func1( x )
    real, intent(in) :: x

    ! your function body goes here

end function func1

end program tabulate_f

Jedną z zalet jest fakt, że kompilator może sprawdzić interfejs funkcji, która jest przekazywana, a ponadto użytkownik ma większą dowolność w użyciu funkcjonalności zapewnioną przez twoją bibliotekę.