4

I am writing an application in Go. However on every platform my code will utilize external program compiled from another project in another language (e.g. C++ in Windows, Objective-C for Mac etc). This external executable is called with os/exec exec.Command function.

I can package my software with no problem, however one issue persists is that using go run will result in this file missing.

Is there a way to tell go that it should include external file (and preferably also build it from source) whenever I do $ go run myproj?

AFAIK, go run simply builds binary under a tmp directory, however it won't include any external files such as images etc. So for example when you have two files: $GOPATH/src/main/main.go and $GOPATH/ext-tool.bin and main.go content is:

package main

import "os/exec"

func main() {
    cmd := exec.Command("./ext-tool.bin")
    err := cmd.Run()
    if err != nil {
        os.Exit(1)
    }
}
Alexey Kamenskiy
  • 2,888
  • 5
  • 36
  • 56
  • First, you shouldn't use `go run` for your project, use `go install` or `go build` If you need a binary included you will need to provide that externally somehow, like any other dependency. – JimB Jan 07 '17 at 17:16
  • @JimB, I am aware how to build and package my application. The issue is I need to DEBUG with this binary included. All debuggers I can see are using `go run`, thus the question. – Alexey Kamenskiy Jan 07 '17 at 17:26
  • Oh, then just make sure the executable is in your PATH, or provide a full path the the executable. You shouldn't rely on a relative path in a binary. – JimB Jan 07 '17 at 17:31
  • @JimB that's what I am doing now. However this is a `coupled` software so debugging it with go app would be so much easier if I can just rebuild and include this external binary automagically on every debugger process restart. – Alexey Kamenskiy Jan 07 '17 at 17:35
  • You can do some trickery to get other things to be included with your source. You may go generate to be helpful, along with something like fileb0x, as mentioned below ( https://stackoverflow.com/a/54028731/151312 ) – coolaj86 Mar 25 '19 at 19:11

1 Answers1

3

One alternative would be to embed your executable in your application build.

This is done with go-bindata or its more recent successor unnoted/fileb0x.
There, you would have access to your embedded executable within an in-memory filesystem.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • That could be an option. Though not for my case because that executable should be ran with different permissions (suid) – Alexey Kamenskiy Jan 08 '17 at 08:46
  • @AlexKey And this would not help? http://stackoverflow.com/a/21706757/6309 – VonC Jan 08 '17 at 08:53
  • Not unless I run it as root, then it makes no sense for my case as I could have embedded this functionality into main app from the start. And that would not solve more general case of having some resource files with the application (like images not converted into []bytes but as a plain files etc). It is rather rare to see application that has no resource files with it... – Alexey Kamenskiy Jan 08 '17 at 09:01
  • To elaborate on `suid`, the app is ran by user, but some actions shuold be perfromed with root privileges, so this `external binary` is a helper tool that has `suid` bit set to allow privilege escalation. That is a recommended and common way of implementing such cases. I have no problem distributing my app this way, but testability suffers a lot as I cannot use any debugger to test these functions as ALL debuggers I've seen use `go run` which means tmp directory and missing resource files – Alexey Kamenskiy Jan 08 '17 at 09:03
  • Also in the comments to the question it was mentioned to load those resources by absolute path, which would work for testing (and that's what I do now), but then packaging the app I have to change resources path to relative since I have no knowledge where user will install the application. And that also affects collaboration since other devs cannot just clone this project and start working, they have to first "setup environemnt" which means copying those files to hardcoded location matching with everyone else. – Alexey Kamenskiy Jan 08 '17 at 09:08
  • @AlexKey could you change the resource path relative to an environment variable? That way, the only environment setup required from other devs would be to set that unique environment variable. – VonC Jan 08 '17 at 09:14
  • @AlexKey Or: could you setup your path relative to the execution path of your executable? Then no setup required. – VonC Jan 08 '17 at 09:14
  • envvar - and then I need to instruct user to configure environment variable? relative path - then `go run` will have resources missing, that is exactly the issue. Go run executes build, but under tmp directory, and it only cares about `.go` files, which literally means there will be executable under /tmp.., but it won't copy resource files to the same location. – Alexey Kamenskiy Jan 08 '17 at 09:17
  • @AlexeyKamenskiy could you please share example/gist of getting handle to executable bundled inside go program and executing that as next step? All I see is read/write file which returns byte[]? I tried both go-bindata and unnoted/fileb0x. Thank you – Puneri Dec 21 '19 at 03:32