Hello Again,

Sorry for the delay.  After some consideration and investigation, I have the
following two proposals:

# Property-Centric
In this proposal, the generation of the scheme files is customized primarily by
a user setting additional, specialized properties on a given target, which then
affect the generation of the scheme files associated with that target.  Scheme
files are persisted as xml, and currently, each scheme file contains six
elements directly underneath the root element which correspond to each of the
[scheme actions](http://help.apple.com/xcode/mac/8.3/#/devd9c8382e7) available
in the scheme editor.

To this end, with one exception, the specialized properties defined for this
purpose will follow the convention `XCODE_SCHEME_<ACTIONNAME>_<CONFIGID>` where
`<ACTIONNAME>` may be one of `BUILD`, `TEST`, `LAUNCH`, `PROFILE`, `ANALYZE`,
`ARCHIVE` and `<CONFIGID>` will be appropriate to the particular item being
configured and detailed further below.  The exception to this convention is the
`XCODE_SCHEME_NAME` property which will be used to override the default name of
the generated scheme that by default matches the name of the target it is
associated to. It can even be set to the empty string in order to completely
disable scheme generation for select targets.

These properties will be ignored by all generators but the Xcode generator.

## CONFIGIDs
Being unable to find official, public documentation on the design and format of
xcode scheme files, experimental analysis has revealed that that there are
approximately three classes of configuration methods used in each action's xml
element.  The first class of options are specified as attributes of the action's
xml element.  The second class of options are specified as elements providing
name/value pairs via attributes and are are children of an `AdditionalOptions`
element in the action element, and the final class is everything else and which
has a different format in each case.

This proposal is primarily concerned with extending and controlling the
configuration of the Launch action and therefore includes CONFIGIDs that apply
to that action, though it is possible and in some cases likely that they will
have general utility in most other actions.  These are as follows:

* `OPTS` - Properties with this config id will be a CMake list of name/value
pairs where the names and values are strings separated by the first embedded
equals sign. Once parsed, the names will be used to identify xml attributes to
set on the action element and the values will of course be the values set on
those attributes.
* `ADTL_OPTS` - Like with the `OPTS` config id, this will be a list of
name/value pairs.  However, the names and values will be used to define xml
elements of the form `<AdditionalOption key="&name;" value="&value;"
isEnabled="YES"/>` which are then added to the `<AdditionalOptions>` element
of the current action.  Note, that there are no provisions for controlling the
`isEnabled` state of an option besides those programmatic elements of CMake
which would make it possible to specify (or not) a given additional option.
It is unclear what the semantic difference is between "options" and
"additional options" as there is no clear distinction in the Xcode UI.
* `RUNNABLE` - This is a simple string which can be interpreted as a target
reference if it matches the name of an executable target in the project, or a
literal path to an executable on the file system otherwise.  In either case,
it specifies the executable which will be run when the scheme is active.  When
no `RUNNABLE` target is specified, the current, default runnable is used.
* `ARGUMENTS` - Is a CMake list of strings that each define an element of the
form `<CommandLineArgument argument="&value;" isEnabled="YES" />` to add to
the `<CommandLineArguments>` element of the current action.  As with
`ADTL_OPTS`, `isEnabled` cannot be changed. These values are passed to the
executable specified by `RUNNABLE` as command line arguments.
* `ENVIRONMENT` - This is similar to `ADTL_OPTS` except the elements created are
of the form `<EnvironemtVariable key="&name;" value="&value;"
isEnabled="YES"/>` and they are added to the `<EnvironmentVariables>` element
of the current action.  These values are used to initialize the process
environment of the executable specified by `RUNNABLE`

## Unexplored/Unsupported
Support for scheme action pre and post actions are not part of this proposal
because it is believed that in order to support them, target property names will
either have to be excessively cumbersome, or the supported functionality will
need to be excessively specialized and limited.

## Explicit list of properties
When conventions above are expanded to meet the needs of the Launch action, this
results in the following six properties which can be applied to any target.

* `XCODE_SCHEME_NAME`
* `XCODE_SCHEME_LAUNCH_OPTS`
* `XCODE_SCHEME_LAUNCH_ADTL_OPTS`
* `XCODE_SCHEME_LAUNCH_RUNNABLE`
* `XCODE_SCHEME_LAUNCH_ARGUMENTS`
* `XCODE_SCHEME_LAUNCH_ENVIRONMENT`

## Generator Expressions
The properties specified for scheme customization should support generator
expressions.  Most notably, `XCODE_SCHEME_NAME` should recognize `$<CONFIG>`,
generating a different scheme file for each configuration.  The value that
`$<CONFIG>` evaluates to for `XCODE_SCHEME_NAME` should persist for every
evaluation of `$<CONFIG>` while a given scheme file is being generated.  If
`$<CONFIG>` is used in a property for which `$<CONFIG>` was not also indicated
in `XCODE_SCHEME_NAME`, the results are undefined.

## Examples

Configure xcode to generate a scheme that will aid in debugging a cli program's
help option
```
add_executable(simple_tool simpletool.c)
set_target_properties(simple_tool
    XCODE_SCHEME_LAUNCH_ARGUMENTS --help)
```

Configure schemes that build specific shared libraries to execute a common
executable target.
```
add_library(tools1 SHARED tools1.c)
add_library(tools2 SHARED tools2.c)
add_executable(main main.c)
target_link_libraries(main tools1 tools2)

set_target_properties(tools1 tools2
    XCODE_SCHEME_NAME "$<TARGET:NAME>|$<CONFIG>"
    XCODE_SCHEME_LAUNCH_OPTS "buildConfiguration=$<CONFIG>"
    XCODE_SCHEME_LAUNCH_RUNNABLE main)
```

Enable test tooling built in to the app via an environment variable and coax the
linker in to loading the Qt debug libraries
```
add_executable(qtapp qtmain.cpp)
set(_env
    "ENABLE_TEST_TOOLBAR=1"
    "$<$<CONFIG:debug>:DYLD_IMAGE_SUFFIX=_debug>")
set_target_properties(qtapp
    XCODE_SCHEME_NAME "qtapp -- $<CONFIG>"
    XCODE_SCHEME_ENVIRONMENT ${_env})
```

# Scheme-File-centric
While the property-centric proposal described above seems relatively capable,
and it follows conventions established by the `MACOSX_*`, `VS_*`, `XCODE_*`
properties already defined and others, they seem fairly invasive, high
maintenance, and they do not allow schemes targeting built-in projects (such as
ALL_BUILD) to be customized.  Further, it seems as though scheme/target
relationships are basically 1:1.  Apart from configuration variants, it is not
possible to have more than one scheme reference a given target as a build
dependency, and it is certainly not possible to have the build action of a
scheme build more than a single top-level target.

I believe all of these issues could be addressed and additional leverage given
to users to utilize the full abilities of schemes now and in the future, by
adding two additional CMake features.

The first is to add a flag to `configure_file` that will cause it to run during
the generation phase and therefore be able to expand generator expressions.

The second is to define an xcode-specific read-only target property:
`XCODE_BLUEPRINT_ID`.

Once these constructs are available, a user could configure files with bits of
xml that look like this:
```xml
<BuildableReference
   BuildableIdentifier = "primary"
   BlueprintIdentifier = "$<TARGET_PROPERTY:footarget,XCODE_BLUEPRINT_ID>"
   BuildableName = "ALL_BUILD"
   BlueprintName = "ALL_BUILD"
   ReferencedContainer = "container:foo.xcodeproj">
```

I believe that the fact that the blue print id for a given target changes on
each generation, is the only thing preventing scheme files from being manually
(and flexibly) created during the configure phase.

In full disclaimer: I have not investigated the feasibility of implementing such
a solution

Thanks,
Steven

On Fri, Sep 15, 2017 at 11:48 AM, Steven Velez <sbv1...@gmail.com> wrote:
> Sure.. but I haven't even thought about it much yet.  So when that has
> happened, I'll make a more formal proposal.
>
> Thanks,
> Steven
>
> On Fri, Sep 15, 2017 at 11:04 AM, Brad King <brad.k...@kitware.com> wrote:
>>
>> On 09/15/2017 10:55 AM, Steven Velez wrote:
>> > I am assuming that the lack of response indicates that there has not
>> > been much thought or interest expressed along this dimension of the
>> > feature.
>> >
>> > Would a better way to approach this be to implement a prototype and
>> > create a WIP MR?
>>
>> Can you post a more specific proposal here?  E.g. with proposed
>> target properties to control it and show some examples.
>>
>> Thanks,
>> -Brad
>
>
-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to