Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Native cgo support infrastructure #269

Closed
@shadowmint

Description

@shadowmint

So, as a summary for this issue, I tried to use https://github.com/therecipe/qt, with dep, and it didn't work; although it downloaded the dependency, it didn't generate all the required files to actually be able to run.

In order to work, the qt binding uses a setup script qtbuild to setup various go packages and generate the various files that cgo can bind to.

This is not an uncommon issue; http://akrennmair.github.io/golang-cgo-slides summarizes the issue with cgo succinctly:

Usually, you want to access functions outside of libc.
Linking to external libraries required; two possibilities:

- Add CGO_LDFLAGS to Makefile
- Embed in .go source file using #cgo directive (preferred)

...and that's pretty much the state of play.

For example:

...solving all the problems with cgo is entirely out of the scope of what dep sets out to do, but perhaps we can standardize on a way of supporting the basic cgo workflow.

What do other languages do?

If you look at python (setup.py), rust (build.rs), node (post-install scripts), even java (maven plugins) you'll see a commonality in the package managers; arbitrary post-install script execution to do various things, including compile C dependencies.

However, if we look closely at a recent example, rust, this model hasn't been particularly successful; although build.rs can execute arbitrary code, and you can have 'build dependencies' to import helper scripts, ultimately the configuration and usage of these scripts is brittle and difficult to get right.

The guidelines in http://doc.crates.io/build-script.html are complex; and people get it wrong. Despite the best efforts of its contributors https://github.com/PistonDevelopers/Piston continues to generate a stream of 'I tried it but it didn't compile...' problems for people.

What do we actually want?

Before looking at any specific solution, perhaps we can look at what we actually want to achieve.

In a nutshell, what we need is some kind of 'extra step':

    1. Dep installs packages in vendor/
    1. ??? <--- Extra step here
    1. You can issue a build command against code using cgo and it works.

That 'extra step' needs to be able to, potentially any of:

  • Check if build tools are available on the system.
  • Actually build c libraries.
  • Generate go code.
  • Prompt the user with custom install instructions to install system level libraries.

For example, ages ago I wrote this demo for generating a static C library and embedding it using cgo to generate a 'single binary' go executable that embeds its own c dependency.

However, to do that you need to do this:

mkdir build
cd build
cmake ..
cmake --build .
cd ..
go build
./demo

There's no facility to turn this into a package that you can go get; there's no means to inform the user that there is a custom step they need to run, and no means to automatically run it.

So what now?

Well, so that's where we are now.

You could argue that supporting this is beyond the scope of dep, and that this is an issue that needs to be raised at a high level in the go toolchain itself, and that's a fair argument.

However, I think we could plausibly look at a way that dep can help standardize the way packages with dependencies are crafted, since the goal of dep is, itself, to standardize the way we handle dependencies in general.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions