DEV Community

George Calianu
George Calianu

Posted on

5

Conditional compilation and runtime module names in Go

#go

Conditional compilation in Go language is a very nice feature but what if we want to know at runtime what modules we just compiled (do not confuse with the new Go modules!). We can define a file as a particular module of our application. So, knowing that if the files are compiled or not can be interesting but we haven't a standard mechanism to do this at runtime.

Let supose we have three dummy files main.go, module1.go and module2.go doing nothing and part of package main.

main.go file

package main

func main() {
}

module1.go file

//+build module1

package main

module2.go file

//+build module2

package main

Build arguments are given at compile time as tags, eg.:

 go build -tags="module1 module2" -o test

Unfortunately the build args are no more accesible after the compiling process, nowhere are writen what was compiled and what not. If we want for example at runtime to print the efective compiled files we simply can't.

Here it come the tricky part. In Go runtime package we have the Caller() function who knows the current invocation file and can be used to identify if the file is compiled or not. So, our dummy program become like following.

main.go file

package main

import (
    "fmt"
    "path/filepath"
    "runtime"
    "strings"
)

var mods []string

// include this in every init() function to detect linked modules
func _init() {
    _, file, _, _ := runtime.Caller(1)
    mods = append(mods, strings.TrimSuffix(filepath.Base(file), ".go"))

}
func init() {
    _init()
}

func main() {
    fmt.Println(mods)
}

module1.go file

//+build module1

package main

func init() {
    _init()
}

module2.go file

//+build module2

package main

func init() {
    _init()
}

We has defined _init() function which we will include in every init() functions from every module. At runtime init() functions will update an array of names which can be easy printed. The Caller() parameter mean the nesting level.

Running again.

go build -tags="module1 module2" -o test
./test
[main module1 module2]
go build -tags="module1" -o test
[main module1]

This technique suppose that you will have a consistency between the file name and build tags, so, be care to this aspect to avoid confusion.

Enjoy.

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

While many AI coding tools operate as simple command-response systems, Qodo Gen 1.0 represents the next generation: autonomous, multi-step problem-solving agents that work alongside you.

Read full post

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay