반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- getopts
- newSQL
- Preprocessor
- kernel
- Symbol
- SQLite
- Pointer
- UNIX
- 포인터변수
- 포인터
- 커널
- Programming
- DBMS 개발
- 전처리기
- TiDB
- TiKV
- go
- Golang
- OS 커널
- 구조와 원리
- UNIX Internals
- 함수포인터
- bash
- 한빛미디어
- 컴퓨터 강좌
- DBMS
- 긴옵션
- Windows via c/c++
- 약어
- FreeBSD
Archives
- Today
- Total
sonumb
Go - release/debug 모드 빌드하기 - 1 본문
개요
빌드 시, 릴리즈 모드에 따라 호출되는 함수의 기능을 달리하고 싶을 때가 있다.
"모드에 따른 다른 빌드"를 구현하는데, 두 가지 방법이 있다.
두 방안에 대해 알아보고, 두 방안의 성능차이도 실제 측정하여 기록하였다. (이 주제의 두번째 게시물 마지막)
방안들
1. 빌드 시, 태그(-tags
) 옵션을 이용하는 방법
파일을 두 개 동일하게 생성하되
그중 하나가 디버깅이라면 // +build debug
을 맨 윗줄에,
디버깅이 아닌 것은 // +build |debug
을 소스코드 파일 맨 윗줄에 추가한다.
태그 옵션을 이용하여 모드에 따른 빌드는 가능하다.
⛔️ 주의 그러나 시스템 종속족인 기능과 같이, 빌드 시 "내용이 파일에서 분리가 되어야 하는 것"들인 경우 이를 이용하는게 가장 좋다. 왜냐하면, Go는 C/C++과 달리 프리프로세스가 없기 때문이다(😦) 따라서, 어떤 기능을 구현하는데, 호출해야 할 시스템 콜이 아예 없는 경우에 시스템별로 아예 파일들을 분리하여 각각 다른 파일에 내용을 작성하는 것이 맞다. |
2. 빌드 시, 특정 변수에 모드를 기록. 이 변수를 이용하는 방법.
빌드시 특정 옵션으로 소스코드 내에 변수를 조작할 수 있을까? 가령 go build --set-value-into-variable-of-file='MODE=Debug' -o fooServer
으로 실행하면 소스코드내에 var MODE = ""
가 "Debug"
로 변경되는 것을 기대할 수 있을까?
가능하다.
build 옵션에 ldflags 를 이용하여 소스 코드내 변수를 변경할 수 있다. (대개 버전 정보라던가, 패키지 이름을 바이너리 내에 기록하기 위해 이용한다.) 그렇다면 빌드시 모드를 기록하면, 모드에 따라 다른 함수가 호출이 가능할 것이다.
소스코드
아래는 위 1번 방안에 대한 소스코드다.
(2번 방안에 대한 소스코드는 2편에서...: )
https://sonumb.tistory.com/123
main.go
파일
package main
import (
"fmt"
"time"
)
func foo() {
_, _, fnname, err := GetTraceInfo()
if err == nil {
println(fnname)
}
time.Sleep(time.Second)
fmt.Println("foo() : done")
}
func bar() {
Trace()
time.Sleep(1 * time.Second)
fmt.Println("bar() : done")
}
func main() {
foo()
bar()
}
trace_debug.go
파일
// +build debug
package main
import (
"fmt"
"runtime"
"errors"
)
func GetTraceInfo() (string, int, string, error) {
pc, file, line, ok := runtime.Caller(1)
if ok == false {
return "", 0, "", errors.New("invalid calling")
}
fn := runtime.FuncForPC(pc)
if fn == nil {
return "", 0, "", errors.New("unknown method")
}
return file, line, fn.Name(), nil
}
func trace() {
pc, file, line, ok := runtime.Caller(1)
if ok == false {
return
}
fnName := ""
fn := runtime.FuncForPC(pc)
if fn != nil {
fnName = fn.Name()
}
fmt.Printf("%s:%d %s()\n", file, line, fnName)
}
trace.go
파일
// +build !debug
package main
import (
"runtime"
"errors"
)
func GetTraceInfo() (string, int, string, error) {
pc, file, line, ok := runtime.Caller(1)
if ok == false {
return "", 0, "", errors.New("invalid calling")
}
fn := runtime.FuncForPC(pc)
if fn == nil {
return "", 0, "", errors.New("unknown method")
}
return file, line, fn.Name(), nil
}
func trace() {
return
}
✅ 눈썰미가 좋은 분은 아시겠지만, GetTraceInfo() 함수가 중복되어 선언되어 있다. 따라서 중복제거를 위해 하나의 파일에 선언하면, trace를 위한 파일이 하나가 더 늘어난 총 3개가 생긴다. 관리해야할 파일이 늘어나는 점이 태깅옵션의 단점이자 장점이기도 하다. 흠.. |
Makefile
파일
all: release
release:
go build -o buildSystem
debug:
go build -tags debug -o buildSystem
clean:
rm buildSystem
실행 및 결과
$ make clean all; ./buildSystem
rm buildSystem
go build -o buildSystem
main.foo
foo() : done
bar() : done
$ make clean debug; ./buildSystem
rm buildSystem
go build -tags debug -o buildSystem
main.foo
foo() : done
/Users/sonumb/work/go_exam/buildsystem/main.go:19 main.bar()
bar() : done
$
반응형