Categorygithub.com/pijng/go-ifdef
modulepackage
0.0.9
Repository: https://github.com/pijng/go-ifdef.git
Documentation: pkg.go.dev

# README

go-ifdef

Add trivial #ifdef, #else and #define macros to your go code.

go-ifdef has built-in support for GOOS in form of #ifdef GOOS:<target>

You can use any valid GOOS value.

Usage

  1. Install go-ifdef with:
go install github.com/pijng/go-ifdef@latest
  1. Build your project with go build while specifying go-ifdef preprocessor:
go build -a -toolexec="go-ifdef" main.go

Important:

  • -a flag is required to recompile all your project, otherwise go compiler might do nothing and use cached build
  1. Run the final binary:
./main

Demonstration

Suppose we have this code:

package main

import "fmt"

func main() {
	var i int

	// #ifdef GOOS:darwin
	i = 100
	// #else
	i = 727
	// #endif

	fmt.Println(i)
}

If we compile it for MacOS and apply go-ifdef as a preprocessor, then we'll get the following result:

$ env GOOS=darwin go build -a -toolexec="go-ifdef" main.go
$ ./main
100
$

But if we change the directive to linux, for example like this:

package main

import "fmt"

func main() {
	var i int

	// #ifdef GOOS:linux
	i = 100
	// #else
	i = 727
	// #endif

	fmt.Println(i)
}

and then compile it to the same MacOS, then we'll get different result:

$ env GOOS=darwin go build -a -toolexec="go-ifdef" main.go
$ ./main
727
$

Or another example with conditional struct populating:

package main

import "fmt"

func main() {
	fmt.Printf("%+v\n", someResult())
}

type result struct {
	os    string
	items []int
}

func someResult() result {
	res := result{os: "Not windows"}
	res.items = append(res.items, []int{1, 2, 3}...)

	// #ifdef GOOS:windows
	res.os = "windows!"
	res.items = append(res.items, []int{4, 5}...)
	// #endif

	return res
}

If we compile this code for a platform other than Windows, then upon execution, we will get the following:

$ env GOOS=linux go build -a -toolexec="go-ifdef" main.go
$ ./main
{os:Not windows items:[1 2 3]}
$

But if we compile it for Windows, we'll get this instead:

$ env GOOS=windows go build -a -toolexec="go-ifdef" main.go
$ ./main
{os:windows! items:[1 2 3 4 5]}
$

Custom directives

You can define custom directives with #define keyword. ⚠️ Only boolean values are supported

For example:

package main

import "fmt"

// #define DEBUG true

func main() {
	fmt.Printf("%d\n", someResult())
}

func someResult() int {
	// #ifdef DEBUG
	fmt.Println("DEBUGGING")
	// #else
	fmt.Println("NOT DEBUGGING")
	// #endif

	return 0
}

If we compile it and run:

$ go build -a -toolexec="go-ifdef" main.go
$ ./main
DEBUGGING
0
$

But if we change #define DEBUG to false:

package main

import "fmt"

// #define DEBUG false

func main() {
	fmt.Printf("%d\n", someResult())
}

func someResult() int {
	// #ifdef DEBUG
	fmt.Println("DEBUGGING")
	// #else
	fmt.Println("NOT DEBUGGING")
	// #endif

	return 0
}

Then the result will be different:

$ go build -a -toolexec="go-ifdef" main.go
$ ./main
NOT DEBUGGING
0
$

Or you can pass a directive value with env when invoking go build command:

package main

import "fmt"

// #define DEBUG

func main() {
	fmt.Printf("%d\n", someResult())
}

func someResult() int {
	// #ifdef DEBUG
	fmt.Println("DEBUGGING")
	// #else
	fmt.Println("NOT DEBUGGING")
	// #endif

	return 0
}

If we pass DEBUG=true with env and compile this code:

$ env DEBUG=true go build -a -toolexec="go-ifdef" main.go
$ ./main
DEBUGGING
0
$

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author