Building Go module without main file
Asked Answered
T

3

9

I have a small module that contains some shared code. The module looks like the following :

Shared
├── go.mod
├── go.sum
├── logging
│   └── logger.go
└── db-utils
    ├── db.go

If I'll try to build the Shared module from inside the directory I'm getting an error that no go file available under this module.

bash-3.2$ go build .
no Go files in /Users/xxxx/go/src/Shared

Is there a way to build a Go module that only has packages inside and doesn't have a main.go file? The motivation here is to use those packages in other go modules that can't access the internet or private repo in order to retrieve the packages.

Tropho answered 22/6, 2021 at 8:24 Comment(12)
golang.org/cmd/go/#hdr-Compile_packages_and_dependenciesSycee
I used go build, can you point to the relevant part in the docs ?Tropho
@Tropho You don't build modules. You build packages. When using go.mod, you append relative package path to module name to identify the package. If you really want to build both packages with one invocation of go build you will have to list them both at the end of the command, or import them with blank imports in a .go file in .Sycee
golang.org/cmd/go/#hdr-Package_lists_and_patternsMythomania
Try go build ./...Heparin
@Sycee What do you mean by you dont build modules ? If I have a service that I develop and inside I have multiple packages I want to create an executable file that contains all the content of the module - all the packages. Isnt a module a wrapper of multiple packages ?Tropho
@ChenA. I run the command successfully but i'm not sure what is the result. I dont see any new fileTropho
@Tropho In that case, you only really build your main package. That everything else also gets compiled is merely a consequence of your main package importing it, directly or indirectly. The reason you get no build artifact out of a non-main package is because Go quite religiously only builds from source. Effectively, there are no binary build artifacts for "libraries" (read: non-main packages); only for "commands", i.e. main packages. This has been the case for some time. See github.com/golang/go/issues/28152 and golang.org/pkg/go/build/#hdr-Binary_Only_PackagesSycee
A honorable mention goes out to golang.org/pkg/plugin but I emphasize that it's a work in progress which e.g. does not work on Windows, yet.Sycee
@Sycee Thanks for the clear explanation ! So basically, my only option is to build every package (get file per package). It will be gr8 if you can post your explenation as a comment so that i can mark it as an answerTropho
"I want to create an executable file" - then you need to build a main package. main() is the entry point to an executable, without it you cannot build an executable.Vorous
What if I don't care for an output file but want to check that the shared library actually all compiles together? How do I say "go build ./..."?Parietal
R
4

The go command stores downloaded modules in the module cache as source code, not compiled object files. go build rebuilds the object files on demand and stores them in a separate build cache.

If you want to distribute a non-public module for use with other modules, you have a few options:

  1. You can publish the module to a private repository — typically accessed with credentials stored in a .netrc file — and use the GOPRIVATE environment variable to tell the go command not to try to fetch it from the public proxy and checksum servers.

  2. You can provide a private GOPROXY server or directory containing the source code, and use the GOPROXY environment variable to instruct the go command to use that proxy.

  3. You can publish the source code as a directory tree and use a replace directive in the consumer's go.mod file to slot it into the module graph.

Rafaello answered 28/6, 2021 at 19:25 Comment(0)
W
6

If you only needed to build files in either the logging or db-utils directory, then you could executing the following from the root directory Shared:

go build <INSERT_MODULE_NAME_FROM_GO_MOD>/logging
go build <INSERT_MODULE_NAME_FROM_GO_MOD>/db-utils

I'm not certain if those commands will work if one of the files has a dependency on a file from the other directory.

Another command that will probably build the entire project is this:

go build ./...
Wham answered 1/3, 2022 at 21:21 Comment(1)
This solution worked for me. I found it to be useful because all I wanted to do was to check if the .go files were syntactically correct and catch any obvious compiler errors in my CI pipeline.Milissamilissent
R
4

The go command stores downloaded modules in the module cache as source code, not compiled object files. go build rebuilds the object files on demand and stores them in a separate build cache.

If you want to distribute a non-public module for use with other modules, you have a few options:

  1. You can publish the module to a private repository — typically accessed with credentials stored in a .netrc file — and use the GOPRIVATE environment variable to tell the go command not to try to fetch it from the public proxy and checksum servers.

  2. You can provide a private GOPROXY server or directory containing the source code, and use the GOPROXY environment variable to instruct the go command to use that proxy.

  3. You can publish the source code as a directory tree and use a replace directive in the consumer's go.mod file to slot it into the module graph.

Rafaello answered 28/6, 2021 at 19:25 Comment(0)
S
2

Is there a way to build a go module that only has packages inside and doesn't have a main.go file?

No. The input for the build process is a package, not a module. Note how it says [packages] in the CLI documentation of go build.

When building a package leads to multiple packages being compiled, that is merely a consequence of direct and indirect import statements coming from .go-files located in the package you are building.

Note that Go does not support compiling packages to binaries to distribute closed-source libraries or such. This was not always the case, though. See #28152 and Binary-Only packages. The closest which exists to supporting that are plugins, but they are a work in progress and require resolution of symbols at runtime.

Sycee answered 22/6, 2021 at 12:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.