[MacPorts] #56002: muniversal portgroup: treat merger_* list variables as lists!

MacPorts noreply at macports.org
Fri Mar 9 22:20:03 UTC 2018


#56002: muniversal portgroup: treat merger_* list variables as lists!
------------------------+------------------------
 Reporter:  ryandesign  |      Owner:  ryandesign
     Type:  defect      |     Status:  new
 Priority:  Normal      |  Milestone:
Component:  ports       |    Version:
 Keywords:              |       Port:  muniversal
------------------------+------------------------
 The muniversal portgroup has a number of associative array variables whose
 elements should be treated as lists (because the MacPorts base options
 they're associated with are treated as lists) but aren't:

 * `merger_build_args`
 * `merger_build_env`
 * `merger_configure_args`
 * `merger_configure_cflags`
 * `merger_configure_cppflags`
 * `merger_configure_cxxflags`
 * `merger_configure_env`
 * `merger_configure_ldflags`
 * `merger_configure_objcflags`
 * `merger_destroot_args`
 * `merger_destroot_env`
 * `merger_test_args`
 * `merger_test_env`

 This results in ports having to use nonstandard quoting characters and
 convoluted escaping when passing in multiple values.

 -----

 Consider port babel @0.1.44 which does this:

 {{{
 if {![variant_isset universal]} {
     configure.env-append CC_FOR_BUILD="${configure.cc}
 ${configure.cc_archflags}"
 } else {
     foreach arch ${configure.universal_archs} {
         lappend merger_configure_env(${arch})
 CC_FOR_BUILD='${configure.cc} -arch ${arch}'
     }
 }
 }}}

 This works, but note the use of the nonstandard quote character `'` when
 setting `merger_configure_env(${arch})`. If the standard quote character
 `"` is used instead, `CC_FOR_BUILD` is not added to the environment at
 all.

 -----

 Consider leveldb @1.19 which does this:

 {{{
 if { [variant_isset universal] } {
     foreach arch ${configure.universal_archs} {
         set merger_build_env(${arch}) "CFLAGS=\"-arch ${arch}\"
 CXXFLAGS=\"-arch ${arch}\" LDFLAGS=\"-arch ${arch} -L${prefix}/lib\""
     }
 } else {
     build.env-append \
         CFLAGS="[get_canonical_archflags cc]" \
         CXXFLAGS="[get_canonical_archflags cxx]" \
         LDFLAGS="[get_canonical_archflags ld] -L${prefix}/lib"
 }
 }}}

 This works, but there's a lot of inconvenient escaping needed to shoehorn
 all of the desired variables into a single string to pass to
 `merger_build_env(${arch})`. If the more natural `lappend` is used to
 append individual arguments, again the variables silently don't end up in
 the environment.

 -----

 Consider mlt @6.4.1 which does this:

 {{{
 if {[variant_isset universal]} {
     foreach arch ${configure.universal_archs} {
         lappend merger_build_env(${arch})
 {*}"CFLAGS='${configure.cflags} -arch ${arch}'"
         lappend merger_build_env(${arch})
 {*}"CXXFLAGS='${configure.cxxflags} -arch ${arch}'"
         lappend merger_build_env(${arch})
 {*}"LDFLAGS='${configure.ldflags} -L${worksrcpath}-${arch}/src/framework
 -L${prefix}/lib -arch ${arch}'"
     }
 } else {
     build.env-append                        CFLAGS="${configure.cflags}
 [get_canonical_archflags cc]"
     build.env-append
 CXXFLAGS="${configure.cxxflags} [get_canonical_archflags cxx]"
     build.env-append                        LDFLAGS="${configure.ldflags}
 -L${worksrcpath}/src/framework -L${prefix}/lib [get_canonical_archflags
 ld]"
 }
 }}}

 Having to use the expansion operator and enclose the entire flag value in
 quotes is certainly strange enough that many developers wouldn't know to
 do that.

 -----

 Consider lp_solve @5.5.23 which does this:

 {{{
 if {[variant_isset universal]} {
     set merger_must_run_binaries yes
     foreach arch ${configure.universal_archs} {
         lappend merger_build_args(${arch}) CC='${configure.cc} -arch
 ${arch}'
     }
 } else {
     build.args-append CC='${configure.cc} ${configure.cc_archflags}'
 }
 }}}

 MacPorts base handles `*.args` differently than `*.env`. Again note the
 unfortunate use of the nonstandard quote character `'`. It works:

 {{{
 Executing:  cd "..." && /usr/bin/make -j8 -w all PREFIX="/opt/local"
 CC='/usr/bin/clang -arch x86_64'
 }}}

 But if it's changed to `"`, the portgroup introduces incorrect escaping,
 which causes `make` to fail with a usage message.

 {{{
 Executing:  cd "..." && /usr/bin/make -j8 -w all PREFIX="/opt/local"
 CC=\"/usr/bin/clang -arch x86_64\"
 }}}

 It becomes even more problematic if one wants to include a list of more
 than one item. Demonstrating this using `${configure.ldflags}`:

 {{{
         lappend merger_build_args(${arch}) CC='${configure.cc}
 ${configure.ldflags} -arch ${arch}'
 }}}

 Result:

 {{{
 Executing:  cd "..." && /usr/bin/make -j8 -w all PREFIX="/opt/local"
 CC='/usr/bin/clang {-L/opt/local/lib -Wl,-headerpad_max_install_names}
 -arch x86_64'
 }}}

 -----

 All of these issues and more can be fixed in the portgroup by simply
 expanding the list with `{*}` before using it to append to or delete from
 the associated MacPorts base option. I've tested several ports that use
 these `merger_*` variables and they seem to be unaffected by the change,
 which makes sense, since in Tcl a list is a string, so all the existing
 usage of passing a single string would be treated as a list of one item
 which is fine.

--
Ticket URL: <https://trac.macports.org/ticket/56002>
MacPorts <https://www.macports.org/>
Ports system for macOS


More information about the macports-tickets mailing list