Distribuição dos seus programas#

Quando fornecer seus programas, há uma diversidade de opções que você pode optar:

  1. Distribuir o código fonte completo

  2. Distribuir um programa executável já compilado

  3. Distribuir bibliotecas estáticas e dinâmicas que as pessoas podem usar

Opção 1: Distribuir o código fonte completo

De longe o mais - para você como programador - é essa: você deixar para o usuário realizar o build na própria máquina. Infelizmente, isso significa que você terá que fazer um sistema de build «user-friendly» e usuário terá que ter aceso aos compiladores adequados. Para sistemas de geração build: veja a seção anterior.

Opção 2: Distribuir um programa executável já compilado

Um programa pré-compilado que não precisa ser customizado, a não ser através de suas entradas, ainda precisará ser distribuído com várias bibliotecas usadas em tempo de execução ou serão específicas ao sistema operacional/ambiente que foi gerado o build para ele.

O conjunto de bibliotecas executadas em tempo de execução diferem por sistema operacional e versão do compilador. Para uma compilador disponível gratuitamente como o fortran, a coisa mais fácil é solicitar ao usuário que instale o compilador no seu sistema. No caso do Windows: o ambiente Cygwin é uma opção.

Alternativamente, você pode fornecer cópias das bibliotecas usadas em tempo de execução junto com seu programa. Coloque-os no diretório onde podem ser encontradas em tempo de execução.

Nota: No Windows, o Intel Fortran vem com um conjunto de bibliotecas redistribuíveis. Elas precisam estar disponíveis.

No geral: usa uma ferramenta como «Idd» ou «dependency walker» para encontrar quais bibliotecas são requisitadas e consulte a documentação do compilador.

Se seu programa permite customização, considere usar bibliotecas dinâmicas para isso. Mais sobre isso é dito abaixo.

Opção 3: Distribuir bibliotecas estáticas ou dinâmicas que as pessoas possam usar

Essa opção é uma combinação das duas primeiras. Isso coloca algum trabalho para o usuário, já que eles precisam criar o programa principal que chama suas rotinas de um jeito apropriado, mas eles não precisam saber muito sobre o sistema de geração de build que você usou. De toda forma, você vai precisar lidar com as bibliotecas usadas em tempo de execução.

Se você escolher essa opção, além das bibliotecas compiladas, você precisará fornecer também os arquivos de módulo intermediários. Esses arquivos são específicos de compilador, mas suas bibliotecas estáticas também são.

Distribuindo o programa de tabulação#

Como mostrado acima, o programa de tabulação pode ser construído com a função definida pelo usuário em uma biblioteca dinâmica. Isso permite que você:

  • Distribua o executável (com as bibliotecas usadas em tempo de execução apropriadas)

  • Forneça uma versão base do módulo, algo como:

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
  • Forneça um script básico de geração de build com um comando como:

gfortran -o functions.dll functions.f90 -shared

ou:

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

Como dito, você não pode garantir que o usuário fez a coisa certa - qualquer DLL «functions.dll» com a função f será aceita, mas não necessariamente levará a uma execução bem sucedida.

Uma alternativa de montagem seria trocar o programa principal por uma subrotina e transformar a função em um argumento:

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

Então forneça uma programa principal base:

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

A vantagem é que o compilador pode checar a interface da função que é passada e o usuário tem mais liberdade no uso da funcionalidade fornecida pela sua biblioteca.