cabal
cabal copied to clipboard
Inconsistent handling of `UnqualComponentName`
Describe the bug
cabal-install appears to allow using component names that Cabal can't parse. I'm not sure if this a bug with cabal-install being too lax or Cabal being too strict.
To Reproduce Steps to reproduce the behavior:
$ cat example.cabal
cabal-version: >= 1.8
name: example
version: 0.0.0.0
build-type: Simple
executable x-1
build-depends: base
main-is: Main.hs
$ cat Main.hs
main = pure ()
$ cabal v2-run x-1
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- example-0.0.0.0 (exe:x-1) (first run)
Configuring executable 'x-1' for example-0.0.0.0..
Preprocessing executable 'x-1' for example-0.0.0.0..
Building executable 'x-1' for example-0.0.0.0..
[1 of 1] Compiling Main ( Main.hs, /private/var/folders/dw/qn5kg6091gq3x8_106kw6ptm0000gn/T/tmp.h2GBaNkl/dist-newstyle/build/x86_64-osx/ghc-9.0.1/example-0.0.0.0/x/x-1/build/x-1/x-1-tmp/Main.o )
Linking /private/var/folders/dw/qn5kg6091gq3x8_106kw6ptm0000gn/T/tmp.h2GBaNkl/dist-newstyle/build/x86_64-osx/ghc-9.0.1/example-0.0.0.0/x/x-1/build/x-1/x-1 ...
Expected behavior
I would expect either cabal-install to reject the component for having an invalid name, or for Cabal to successfully parse the component name.
System information
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H1217
$ uname -a
Darwin TayBook.local 19.6.0 Darwin Kernel Version 19.6.0: Thu May 6 00:48:39 PDT 2021; root:xnu-6153.141.33~1/RELEASE_X86_64 x86_64
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.0.1
$ cabal --version
cabal-install version 3.4.0.0
compiled using version 3.4.0.0 of the Cabal library
Additional context
I discovered this problem on accident by looking at this package: https://hackage.haskell.org/package/hsc3-graphs-0.15. It has many components. I eventually narrowed it down to runs of numbers, like hsc3-berlin-1977. I assume the parser rejects names like this because they might accidentally be confused with version numbers.
Oops, I meant to include a snippet showing Cabal being unable to parse that component name:
ghci> eitherParsec @UnqualComponentName "x1"
Right (UnqualComponentName "x1")
ghci> eitherParsec @UnqualComponentName "x-1"
Left "\"<eitherParsec>\" (line 1, column 4):\nunexpected end of input"
ghci> eitherParsec @UnqualComponentName "x-1-x"
Left "\"<eitherParsec>\" (line 1, column 5):\nunexpected Empty component, after x-1"
Confirmed. This seems to be a Cabal bug, not a cabal-install one. The package description parser (in Cabal) somehow accepts that component name, even when called through Setup.hs (without cabal-install)
The (generic) package description parser appears to use a special parser for component names rather than using the Parsec instance.
https://github.com/haskell/cabal/blob/00a2351789a460700a2567eb5ecc42cca0af913f/Cabal/src/Distribution/PackageDescription/Parsec.hs#L422-L423
https://github.com/haskell/cabal/blob/00a2351789a460700a2567eb5ecc42cca0af913f/Cabal/src/Distribution/PackageDescription/Parsec.hs#L389-L390
https://github.com/haskell/cabal/blob/00a2351789a460700a2567eb5ecc42cca0af913f/Cabal/src/Distribution/PackageDescription/Parsec.hs#L392-L405
That suggests you can use any SecArgName or SecArgStr as a component name, which does appear to be the case. All of the following work: executable 1, executable 1.2, executable "1", executable -. You can start getting into trouble if you pick a component name that collides with other syntax. For example:
$ grep executable example.cabal
executable "s p a c e"
$ cabal v2-build
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- example-0.0.0.0 (exe:"s p a c e") (first run)
cabal-3.4.0.0: Unrecognised build target 'exe:s p a c e'.
Examples:
- build foo -- component name (library, executable, test-suite or benchmark)
- build Data.Foo -- module name
- build Data/Foo.hsc -- file name
- build lib:foo exe:foo -- component qualified by kind
- build foo:Data.Foo -- module qualified by component
- build foo:Data/Foo.hsc -- file qualified by component
$ grep executable example.cabal
executable ":"
$ cabal v2-build
Resolving dependencies...
Build profile: -w ghc-9.0.1 -O1
In order, the following will be built (use -v for more details):
- example-0.0.0.0 (exe:":") (first run)
cabal-3.4.0.0: Unrecognised build target 'exe::'.
Examples:
- build foo -- component name (library, executable, test-suite or benchmark)
- build Data.Foo -- module name
- build Data/Foo.hsc -- file name
- build lib:foo exe:foo -- component qualified by kind
- build foo:Data.Foo -- module qualified by component
- build foo:Data/Foo.hsc -- file qualified by component
I bumped into this issue again.
I think the intent is for component names to be the same as package names. This is enforced for library names, but not for other types of components. For library names, that makes sense. The default public library implicitly has the same name as the package. Other sub-libraries may be public, in which case you can depend on them with something like a-package:a-library >= 1.2.3. Clearly in those cases the sub-library needs to be constrained somewhat, and matching package names makes a lot of sense.
However for other component types, especially executables, it's unclear how the component name should be constrained. I analyzed packages on Hackage to see what they used for component names. Most of them can be parsed as package names. Of the ones that can't be parsed as package names, the only invalid characters are _:. (underscore, colon, and period). For example:
- inspection-testing has a test suite called
NS_NP. - MagicHaskeller has an executable called
MagicHaskeller.cgi. - ds-kanren has a test suite called
test-unify:.- This appears to be a mistake. Instead of defining a test suite using section syntax (
test-suite x\n), this package puts a colon at the end of the line (test-suite x:\n).
- This appears to be a mistake. Instead of defining a test suite using section syntax (
The original post shows the hsc3-berlin-1977 executable name, which also can’t be parsed as a package name, right?
Yes, that's correct. I was looking for components that used invalid characters in their names.
Looking for component names that are actually invalid package names is a little more complicated. I found 376 of them:
Click to expand list of component names:
01_green_trianglefrom GPipe-Examples02_triangle_texturefrom GPipe-Examples03_green_spherefrom GPipe-Examples04_brass_spherefrom GPipe-ExamplesAPI_Usage_Examplefrom boolectorAnd_gatefrom quipper-demosAnd_listfrom quipper-demosAnd_revfrom quipper-demosArguEdit.binfrom argueditArith_Example2from boolectorArith_Example3from boolectorArith_Examplefrom boolectorArray_Examplefrom boolectorBOGLGP02-OnYourOwn1.hsfrom GLUTBOGLGP02-OpenGLApplication.hsfrom GLUTBenchmark.System.Processfrom streamly-processConst_Examplefrom boolectorDecompose_testfrom quipper-demosFlattening_TAfrom DSHGeneratorTests.hsfrom xcffibGetSetSymbol_Examplefrom boolectorHSGEP_CADensityfrom HSGEPHSGEP_Regressionfrom HSGEPHaskell.Tutorialsfrom HaskellTutorialsIPV6_V6ONLYfrom socketInterop.Conduitfrom streamly-examplesInterop.Pipesfrom streamly-examplesInterop.Streamingfrom streamly-examplesInterop.Vectorfrom streamly-examplesMaclightTest.hsfrom maclightMagicHaskeller.cgifrom MagicHaskellerNS_NPfrom inspection-testingNumberTheory_Testsfrom NumberTheorySit.binfrom SitSystem.Terminfo.Internalfrom terminfo-hsTRS_02from tpdbTest.System.Processfrom streamly-processUF_Example2from boolectorUF_Examplefrom boolectorUnitTest_Applicativefrom deepcontrolUnitTest_Commutativefrom deepcontrolUnitTest_Monad-Level1from deepcontrolUnitTest_Monad-Level2-2from deepcontrolUnitTest_Monad-Level2from deepcontrolUnitTest_MonadMorph-Level1from deepcontrolUnitTest_MonadMorphfrom deepcontrolUnitTest_Monadfrom deepcontrolXML_relativefrom tpdb_Control_Concurrent_Priority_Testsfrom priority-sync_PrioritySync.Internal_Testsfrom priority-sync_PrioritySync_Internal_Testsfrom priority-sync_RandomAccountsfrom blocking-transactions_carettah_main_from carettah_rsagl_process_colorsfrom rsagladd_singlefrom clustertoolsadvise-me-admin.cgifrom Advise-meadvise-me.cgifrom Advise-meaes128_testfrom cipher-aes128agentx_examplefrom agentxanswer.cgifrom smartwordapply_annotatorsfrom concrete-haskellapprox_rand_test_pairedfrom approx-rand-testapprox_rand_testfrom approx-rand-testat_model_filter_datafrom alpino-toolsat_model_oraclefrom alpino-toolsat_model_random_samplefrom alpino-toolsat_model_rescore_datafrom alpino-toolsat_model_statistics_datafrom alpino-toolsbackdropper_consolfrom backdropperbackground_and_multiple_scenariosfrom chuchubackground_failfrom chuchubapc_examplesfrom hgeometrybatch_renamefrom batch-renamebench.hsfrom hpathbench.hsfrom posix-pathsbench_cfrom tzbench_convfrom tzbench_gregfrom tzbenchmark_triefrom PerfectHashbuild_graphsfrom concrete-haskellbvdomain_tests_hhfrom what4bvdomain_testsfrom what4c_alignmentfrom derive-storable-pluginc_alignmentfrom derive-storablecabal-helper-wrapper-v0.7from cabal-helpercall-haskell-from-anything.sofrom call-haskell-from-anythingcanonicalpath_testsfrom system-canonicalpathchalkboard-server-1_9_0_15from chalkboardchalkboard-server-1_9_0_16from chalkboardcheck_ekgfrom nagios-plugin-ekgcombinators_testfrom proto-lens-combinatorscookie.cgifrom cgicounterexamples.cgifrom free-theorems-counterexamplesdata-binary-ieee754_testsfrom data-binary-ieee754data-store-benchmark-01from data-storedatabase-builder.exefrom Advise-medbus_benchmarksfrom dbusdbus_testsfrom dbusdeeplearning_demonstrationfrom deeplearning-hsdeeplearning_testfrom deeplearning-hsdoctest-extract-0.1from doctest-extractdrbg_testfrom DRBGdump_nl80211from netlinkdump_rtnetlinkfrom netlinkeditor-open-test_yaml_file_conduitfrom editor-openeditor-open-test_yaml_filefrom editor-openerr_propfrom hsluaerror.cgifrom cgiex-3-1-relativefrom mdpex-3-1from mdpex-3-2from mdpex.shake-persistfrom shake-persistexample-424from sibeexample0.1from porcupine-coreexample02.1from affectionexample_01from hogre-examplesexample_02from hogre-examplesexample_03from hogre-examplesexample_counterbotfrom slack-apiexample_echobotfrom slack-apiexample_logfrom lumberjackexprs_testsfrom what4extensible-effects-concurrent-example-1from extensible-effects-concurrentextensible-effects-concurrent-example-2from extensible-effects-concurrentextensible-effects-concurrent-example-3from extensible-effects-concurrentextensible-effects-concurrent-example-4from extensible-effects-concurrentfetch_servicefrom concrete-haskellfilesystem_path_testsfrom system-filepathfilesystem_testsfrom system-fileiofixpoint.nativefrom liquid-fixpointfltkhs-test_callfrom fltkhsfollow_pocket_authfrom followfree-theorems-seq-webui.cgifrom free-theorems-seq-webuifree-theorems-webui.cgifrom free-theorems-webuigaussian_blurfrom fridaygenerate_hlatex_user_guidefrom hlatexgenerate_readmefrom prettyprintergeneric-lens-test-24from generic-lensgeneric-lens-test-25from generic-lensghc-pkg-6_8-compatfrom cabal-devghcid_testfrom ghcidgifcurry_clifrom Gifcurrygifcurry_guifrom Gifcurrygnuidn_testsfrom gnuidngroundhog_inspectorfrom groundhog-inspectorgrowing_testfrom proto-lenshaskell_tsne_examplefrom tsnehaskell_tsne_timingfrom tsnehello.cgifrom cgihello_worldfrom pubnubhoed-examples-CNF_unsound_de_Morgan__with_propertiesfrom Hoedhoed-examples-Digraph_not_data_invariant__with_propertiesfrom Hoedhoed-examples-Expression_simplifier__with_propertiesfrom Hoedhoed-examples-Expression_simplifierfrom Hoedhoed-examples-FPretty_indents_too_much__CCfrom Hoedhoed-examples-FPretty_indents_too_muchfrom Hoedhoed-examples-Insertion_Sort_elements_disappearfrom Hoedhoed-examples-Nub-defective-sort__with_propertiesfrom Hoedhoed-examples-Parity_testfrom Hoedhoed-examples-Queens__with_propertiesfrom Hoedhoed-examples-Queens_v1__with_propertiesfrom Hoedhoed-examples-Queens_v2__with_propertiesfrom Hoedhoed-examples-Queens_v3__with_propertiesfrom Hoedhoed-examples-Queens_v4_defect_in_filter__with_propertiesfrom Hoedhoed-examples-Simple_higher-order_functionfrom Hoedhoed-examples-SummerSchool_compiler_does_not_terminate__with_propertiesfrom Hoedhoed-examples-SummerSchool_compiler_does_not_terminatefrom Hoedhoed-examples-XMonad_changing_focus_duplicates_windows__CCfrom Hoedhoed-examples-XMonad_changing_focus_duplicates_windows__test_onlyfrom Hoedhoed-examples-XMonad_changing_focus_duplicates_windows__using_propertiesfrom Hoedhoed-examples-XMonad_changing_focus_duplicates_windows__with_propertiesfrom Hoedhoed-examples-XMonad_changing_focus_duplicates_windowsfrom Hoedhoed-examples-ZLang_Defect-1from Hoedhoed-examples-ZLang_Defect-2from Hoedhoed-examples-ZLang_Defect-3from Hoedhoed-examples-filter__with_propertiesfrom Hoedhopfield_demonstrationfrom hopfield-networkshopfield_testfrom hopfield-networkshs_sqlite3_testfrom hsSqlite3hsc3-1-1Nifrom hsc3-graphshsc3-1-4Q6from hsc3-graphshsc3-1-4QMfrom hsc3-graphshsc3-1-4QNfrom hsc3-graphshsc3-1-4Qxfrom hsc3-graphshsc3-1-4Twfrom hsc3-graphshsc3-1-4VLfrom hsc3-graphshsc3-1-9from hsc3-graphshsc3-1-Tdfrom hsc3-graphshsc3-adc-16-6-2from hsc3-graphshsc3-berlin-1977from hsc3-graphshsc3-blips-001-hpfrom hsc3-graphshsc3-blips-001-ufrom hsc3-graphshsc3-blips-001from hsc3-graphshsc3-bohlen-pierce-140from hsc3-graphshsc3-bs-070705-mfrom hsc3-graphshsc3-bs-070705from hsc3-graphshsc3-cds-070701-mfrom hsc3-graphshsc3-cds-070701from hsc3-graphshsc3-f0-2012-04-19from hsc3-graphshsc3-f0-454598285861617665from hsc3-graphshsc3-f0-456384156159574016from hsc3-graphshsc3-fb-090531from hsc3-graphshsc3-hh-808from hsc3-graphshsc3-jl-1-Zfrom hsc3-graphshsc3-jr-100515from hsc3-graphshsc3-lso-061101-mfrom hsc3-graphshsc3-lso-061101from hsc3-graphshsc3-nv-ml-2014-06-03from hsc3-graphshsc3-nv-tw-1from hsc3-graphshsc3-nv-tw-2013-01-11from hsc3-graphshsc3-nv-tw-2013-12-04from hsc3-graphshsc3-nv-tw-2014-02-21from hsc3-graphshsc3-nv-tw-2014-06-03from hsc3-graphshsc3-nv-tw-41from hsc3-graphshsc3-nv-tw-54from hsc3-graphshsc3-pkt-00from hsc3-graphshsc3-pkt-07from hsc3-graphshsc3-pkt-26from hsc3-graphshsc3-pkt-28from hsc3-graphshsc3-snare-909from hsc3-graphshsc3-tw-463992770596577280from hsc3-graphshsc3-tw-98315246548172800from hsc3-graphshsfcsh_dofrom hsfcshhxmpp-0.0.1.0-testfrom HXMPPindex.cgifrom smartwordingest_communicationsfrom concrete-haskellingest_jsonfrom concrete-haskellinspect_communicationsfrom concrete-haskellion_examplefrom ionipopt-hs_Test1from ipopt-hsipopt-hs_Test2from ipopt-hsipopt-hs_Test3from ipopt-hsipopt-hs_Testsfrom ipopt-hsiteexprs_testsfrom what4lazyfoo-lesson-01from sdl2lazyfoo-lesson-02from sdl2lazyfoo-lesson-03from sdl2lazyfoo-lesson-04from sdl2lazyfoo-lesson-05from sdl2lazyfoo-lesson-07from sdl2lazyfoo-lesson-08from sdl2lazyfoo-lesson-09from sdl2lazyfoo-lesson-10from sdl2lazyfoo-lesson-11from sdl2lazyfoo-lesson-12from sdl2lazyfoo-lesson-13from sdl2lazyfoo-lesson-14from sdl2lazyfoo-lesson-15from sdl2lazyfoo-lesson-17from sdl2lazyfoo-lesson-18from sdl2lazyfoo-lesson-19from sdl2lazyfoo-lesson-20from sdl2lazyfoo-lesson-43from sdl2libcspm_testsfrom libcspmlogger-0.0.1.0-testfrom HLoggermaam_examplesfrom maammain.fcgifrom battleshipsmdp_clientfrom majordomometric-tests:from metricminiunit_testsfrom Takusenminiunit_testsfrom takusen-oraclemios-1.5.4from miosmios-1.6.0from miosmnist_examplefrom menohmontecarlo-pi-32from splitmixmultiple_featuresfrom chuchumultiple_scenariosfrom chuchumultiple_shootingfrom dynobudname_testfrom ghc-source-genoauth_callbackfrom twitter-conduitoauth_pinfrom lambdatwitoauth_pinfrom twitter-conduitoffset_testfrom text-offsetoptimize-1-testsfrom HUnitoptimize-201408from conduitoptions_testsfrom optionsparsec.from parsecparser_testfrom proto-lenspdftotext.hsfrom pdftotextpg_migratefrom postgresql-ormpolyseq.cgifrom polyseqpprint_examplesfrom ghc-source-genpprint_testfrom ghc-source-genprintinput.cgifrom cgiprofile-256from arb-fftptq.cgifrom PTQpubsub.fcgifrom pubsubredirect.cgifrom cgireport.exefrom Advise-mereport_parfrom xilinx-lavaresize_imagefrom fridayresolv.from resolvrfc-6070from pbkdfrsa_testfrom RSAsalvia.cgifrom salvia-demosample_asteroidsfrom Hatesample_schedulerfrom Hatesample_shapesfrom Hatesample_spritefrom Hatesample_spritesheetfrom Hateshould_failfrom chuchushowAllInputs.cgifrom cgismtLib-test-1from smtLibsmtLib-test-2from smtLibsofa-viz-2000from dynobudsolarman.cgifrom XSaigasolver_parsing_testsfrom what4spec_mainfrom twitter-conduitstart.cgifrom smartwordstatistics.cgifrom ideas-statisticsstore_servicefrom concrete-haskellsw.cgifrom smartwordtableaux.cgifrom tableauxtakusen_testsfrom Takusentakusen_testsfrom takusen-oracletemplate_testsfrom what4test-1from Hoedtest-2from Hoedtest-3from Hoedtest-4from Hoedtest-5from Hoedtest-6from Hoedtest-7from Hoedtest-client-13from react-fluxtest-client-14from react-fluxtest-list-ops:from ds-kanrentest-unify:from ds-kanrentest_FenwickTreefrom FenwickTreetest_Octreefrom Octreetest_Octreefrom point-octreetest_PhiPsifrom hTalostest_corefrom azubitest_hoauthfrom hoauthtest_itemfieldfrom itemfieldtest_layoutfrom itemfieldtest_messagesfrom matterhorntest_opsfrom OnRmttest_parsingfrom ssh-known-hoststest_perffrom Random123test_rsafrom RSAtest_shafrom SHAtest_unixfrom azubitext-from leancheck-instancestftp_uploadfrom tftptutorial-10from LogicGrowsOnTreestutorial-11from LogicGrowsOnTreestutorial-12from LogicGrowsOnTreestutorial-13from LogicGrowsOnTreestutorial-1from LogicGrowsOnTreestutorial-2from LogicGrowsOnTreestutorial-3from LogicGrowsOnTreestutorial-4from LogicGrowsOnTreestutorial-5from LogicGrowsOnTreestutorial-6from LogicGrowsOnTreestutorial-7from LogicGrowsOnTreestutorial-8from LogicGrowsOnTreestutorial-9from LogicGrowsOnTreestwinklebear-lesson-01from sdl2twinklebear-lesson-02from sdl2twinklebear-lesson-04from sdl2twinklebear-lesson-05from sdl2unit_Applicativefrom deepcontrolunit_Commutativefrom deepcontrolunit_Monad-Level1from deepcontrolunit_Monad-Level2-2from deepcontrolunit_Monad-Level2from deepcontrolunit_Monad-factorial2from deepcontrolunit_Monad-factorialfrom deepcontrolunit_MonadMorph-bind2from deepcontrolunit_MonadMorph-bindfrom deepcontrolunit_MonadMorphfrom deepcontrolunit_MonadTrans-2from deepcontrolunit_MonadTrans-ackermannfrom deepcontrolunit_MonadTransfrom deepcontrolunit_Monadfrom deepcontrolunit_Traversablefrom deepcontrolunit_testsfrom concrete-haskellupload.cgifrom cgivgg16_examplefrom menohvolume_meterfrom alsa-pcm-testsx86-64-examplesfrom x86-64bitzgossip_serverfrom zre