Создание нескольких исполняемых файлов в проекте Haskell Stack по умолчанию

Я использовал по умолчанию stack newдля настройки проекта, в котором сервер и клиент являются отдельными исполняемыми файлами. Я изменилpackage.yamlфайл, который кажется правильным (по состоянию на 21 апреля 2020 г. "Руководства пользователя нет"), и добавил новый файл в моюapp каталог называется Client.hs.

Я получил сообщение об ошибке: "Включение обходного пути для основного модуля Main, указанного в списке other-modules, незаконно!"

Как сделать так, чтобы стек собирал как клиент, так и сервер?

Когда я бежал stack build Я получил:

[... clip ...]
Building executable 'ObjectServer' for ObjectServer-0.1.0.1..
[4 of 4] Compiling Client
Linking .stack-work\dist\29cc6475\build\ObjectServer\ObjectServer.exe ...
Warning: Enabling workaround for Main module 'Main' listed in 'other-modules'
illegally!
Preprocessing executable 'Client' for ObjectServer-0.1.0.1..
Building executable 'Client' for ObjectServer-0.1.0.1..
[3 of 3] Compiling Client

<no location info>: error:
    output was redirected with -o, but no output will be generated
because there is no Main module.


--  While building package ObjectServer-0.1.0.1 using:
      D:\HaskellStack\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_3.0.1.0_ghc-8.8.3.exe --builddir=.stack-work\dist\29cc6475 build lib:ObjectServer exe:Client exe:ObjectServer --ghc-options " -fdiagnostics-color=always"
    Process exited with code: ExitFailure 1

Соответствующая часть package.yaml выглядит так:

executables:
  ObjectServer:
    main:                Main.hs
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - ObjectServer
  Client:
    main:                Client.hs
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - ObjectServer

1 ответ

Решение

Здесь есть две проблемы. Во-первых, значение по умолчанию дляother-modules в hpack "все модули в source-dirs Кроме main и модули, упомянутые в when предложение ". Если вы посмотрите на сгенерированный .cabal файла, вы увидите, что в результате этого значения по умолчанию каждый исполняемый файл неправильно включил модуль другого исполняемого файла в свой other-modulesсписок. Во-вторых,main параметр дает исходный файл, содержащий основной модуль, но не меняет имя модуля, ожидаемого GHC от Mainни к чему другому. Следовательно, этот модуль все еще необходимо назватьmodule Main where ...не module Client where..., если вы тоже не добавляете отдельно -main-is Client Вариант GHC.

Итак, я бы посоветовал изменить Client.hs сделать это Main модуль:

-- in Client.hs
module Main where
...

а затем указав other-modules: [] явно для обоих исполняемых файлов:

executables:
  ObjectServer:
    main:                Main.hs
    other-modules:       []
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - ObjectServer
  Client:
    main:                Client.hs
    other-modules:       []
    source-dirs:         app
    ghc-options:
    - -threaded
    - -rtsopts
    - -with-rtsopts=-N
    dependencies:
    - ObjectServer

Похоже, это работает в моем тестировании.

Другие вопросы по тегам