github.com/bitrise-io/go-xamarin@v0.0.0-20211005113058-bf60a8bae851/tools/buildtools/xbuild/xbuild.go (about)

     1  package xbuild
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/bitrise-io/go-utils/command"
    11  	"github.com/bitrise-io/go-utils/pathutil"
    12  	"github.com/bitrise-io/go-xamarin/constants"
    13  )
    14  
    15  // Model ...
    16  type Model struct {
    17  	BuildTool string
    18  
    19  	SolutionPth string
    20  	ProjectPth  string
    21  
    22  	target        string
    23  	configuration string
    24  	platform      string
    25  
    26  	buildIpa       bool
    27  	archiveOnBuild bool
    28  
    29  	customOptions []string
    30  }
    31  
    32  // New ...
    33  func New(solutionPth, projectPth string) (*Model, error) {
    34  	absSolutionPth, err := pathutil.AbsPath(solutionPth)
    35  	if err != nil {
    36  		return nil, fmt.Errorf("Failed to expand path (%s), error: %s", solutionPth, err)
    37  	}
    38  
    39  	absProjectPth := ""
    40  	if projectPth != "" {
    41  		absPth, err := pathutil.AbsPath(projectPth)
    42  		if err != nil {
    43  			return nil, fmt.Errorf("Failed to expand path (%s), error: %s", projectPth, err)
    44  		}
    45  		absProjectPth = absPth
    46  	}
    47  
    48  	return &Model{SolutionPth: absSolutionPth, ProjectPth: absProjectPth, BuildTool: constants.XbuildPath}, nil
    49  }
    50  
    51  // SetTarget ...
    52  func (xbuild *Model) SetTarget(target string) *Model {
    53  	xbuild.target = target
    54  	return xbuild
    55  }
    56  
    57  // SetConfiguration ...
    58  func (xbuild *Model) SetConfiguration(configuration string) *Model {
    59  	xbuild.configuration = configuration
    60  	return xbuild
    61  }
    62  
    63  // SetPlatform ...
    64  func (xbuild *Model) SetPlatform(platform string) *Model {
    65  	xbuild.platform = platform
    66  	return xbuild
    67  }
    68  
    69  // SetBuildIpa ...
    70  func (xbuild *Model) SetBuildIpa(buildIpa bool) *Model {
    71  	xbuild.buildIpa = buildIpa
    72  	return xbuild
    73  }
    74  
    75  // SetArchiveOnBuild ...
    76  func (xbuild *Model) SetArchiveOnBuild(archive bool) *Model {
    77  	xbuild.archiveOnBuild = archive
    78  	return xbuild
    79  }
    80  
    81  // SetCustomOptions ...
    82  func (xbuild *Model) SetCustomOptions(options ...string) {
    83  	xbuild.customOptions = options
    84  }
    85  
    86  func (xbuild Model) buildCommands() []string {
    87  	cmdSlice := []string{xbuild.BuildTool}
    88  
    89  	if xbuild.ProjectPth != "" {
    90  		cmdSlice = append(cmdSlice, xbuild.ProjectPth)
    91  	} else {
    92  		cmdSlice = append(cmdSlice, xbuild.SolutionPth)
    93  	}
    94  
    95  	if xbuild.target != "" {
    96  		cmdSlice = append(cmdSlice, fmt.Sprintf("/target:%s", xbuild.target))
    97  	}
    98  
    99  	// According to official docs this value should include the trailing backslash:
   100  	// https://docs.microsoft.com/en-us/cpp/build/reference/common-macros-for-build-commands-and-properties?view=vs-2019
   101  	solutionDirPth := ensureTrailingPathSeparator(filepath.Dir(xbuild.SolutionPth))
   102  	cmdSlice = append(cmdSlice, "/p:SolutionDir="+solutionDirPth)
   103  
   104  	if xbuild.configuration != "" {
   105  		cmdSlice = append(cmdSlice, "/p:Configuration="+xbuild.configuration)
   106  	}
   107  
   108  	if xbuild.platform != "" {
   109  		cmdSlice = append(cmdSlice, "/p:Platform="+xbuild.platform)
   110  	}
   111  
   112  	if xbuild.archiveOnBuild {
   113  		cmdSlice = append(cmdSlice, "/p:ArchiveOnBuild=true")
   114  	}
   115  
   116  	if xbuild.buildIpa {
   117  		cmdSlice = append(cmdSlice, "/p:BuildIpa=true")
   118  	}
   119  
   120  	cmdSlice = append(cmdSlice, xbuild.customOptions...)
   121  
   122  	return cmdSlice
   123  }
   124  
   125  // String ...
   126  func (xbuild Model) String() string {
   127  	cmdSlice := xbuild.buildCommands()
   128  	return command.PrintableCommandArgs(true, cmdSlice)
   129  }
   130  
   131  // Run ...
   132  func (xbuild Model) Run(outWriter, errWriter io.Writer) error {
   133  	if outWriter == nil {
   134  		outWriter = os.Stdout
   135  	}
   136  	if errWriter == nil {
   137  		errWriter = os.Stderr
   138  	}
   139  
   140  	cmdSlice := xbuild.buildCommands()
   141  
   142  	command, err := command.NewFromSlice(cmdSlice)
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	command.SetStdout(outWriter)
   148  	command.SetStderr(errWriter)
   149  
   150  	return command.Run()
   151  }
   152  
   153  func ensureTrailingPathSeparator(path string) string {
   154  	slash := string(filepath.Separator)
   155  	return strings.TrimSuffix(path, slash) + slash
   156  }