Skip to content
isdnetworks
Go back

서버마다 빌드 도구 버전이 달랐다

내 자리에서 빌드한 것은 되는데 빌드 서버에서 만든 것은 안 됐고 양쪽이 쓴 소스는 같다.

Table of contents

Open Table of contents

컴파일러가 달랐다

소스가 같은데 결과가 다르면 소스 밖에서 차이가 생긴 것이다. svn info 로 양쪽 리비전이 같은 것부터 확인하고 버전을 찍어 봤다.

$ gcc --version
gcc (GCC) 4.8.5     ( 자리)
gcc (GCC) 4.4.7     (빌드 서버)

4.4에는 없는 문법을 쓰고 있어서 내 자리에서는 통과하고 서버에서는 오류가 난다.

이번엔 오류가 나서 바로 알았는데 빌드가 실패하면 그 자리에서 원인을 찾게 된다. 오류가 안 나고 동작만 다른 경우가 더 무섭고 그런 것은 훨씬 늦게 드러난다.

무엇이 다른지 전부 봤다

문제가 컴파일러만이 아닐 수 있어서 빌드에 관여하는 것을 전부 찍어 봤다.

#!/bin/sh
echo "gcc:    $(gcc --version | head -1)"
echo "make:   $(make --version | head -1)"
echo "ld:     $(ld --version | head -1)"
echo "libc:   $(ldd --version | head -1)"
echo "kernel: $(uname -r)"
echo "arch:   $(uname -m)"

두 곳에서 돌려 diff 로 비교했다.

              내 자리          빌드 서버
gcc           4.8.5            4.4.7
make          3.82             3.81
libc          2.17             2.12
kernel        3.10             2.6.32

네 가지가 전부 다르다. 이번 문제의 원인은 컴파일러였지만 나머지도 언젠가 문제가 된다. 하나만 맞추고 끝냈으면 다른 것 때문에 또 같은 일을 겪었을 것이다.

어느 쪽에 맞출지 정했다

두 선택지가 있었다. 빌드 서버를 올리면 배포 대상 서버도 같이 올려야 하고 라이브러리 호환을 봐야 한다. 반대로 내 자리를 낮추면 개발이 불편해진다.

배포 대상 서버가 빌드 서버와 같은 판이었다. 거기서 도는 것이 목적이니 빌드 서버 쪽에 맞추기로 했다. 내 자리가 더 최신이라도 운영과 다르면 맞지 않는 것이다.

내 자리에 옛 버전을 따로 설치하고 그것으로 빌드하게 했다.

/opt/gcc-4.4.7/bin/gcc
CC ?= /opt/gcc-4.4.7/bin/gcc

기본은 옛 버전이고 필요하면 CC 환경 변수로 바꾼다.

빌드 환경 확인 단계

빌드를 시작할 때 컴파일러 버전을 확인하고 안 맞으면 그 자리에서 멈추게 했다.

check-env:
	@v=$$($(CC) -dumpversion); \
	if [ "$$v" != "4.4.7" ]; then \
	  echo "컴파일러 버전 불일치: $$v (기대: 4.4.7)"; \
	  echo "CC 를 확인하십시오. 현재: $(CC)"; \
	  exit 1; \
	fi
	@echo "빌드 환경 확인 완료"

all: check-env $(TARGET)

-dumpversion 으로 받은 값이 다르면 exit 1 이다. 빌드가 시작되기 전에 걸리므로 다 컴파일하고 나서 링크에서 실패하는 것보다 낫다.

검증 — 빌드 정보와 배포 자리

만들어진 실행 파일이 어느 환경에서 나온 것인지 알 수 있게도 했다.

static const char BUILD_INFO[] =
    "built " __DATE__ " " __TIME__
    " gcc " __VERSION__;

void printBuildInfo(void) {
    printf("%s\n", BUILD_INFO);
}

__DATE____TIME__ 은 전처리기가 컴파일 시각으로 바꿔 주는 표준 매크로라 따로 넣을 것이 없고 __VERSION__ 이 컴파일러 판을 준다.

$ ./app --version
built Apr 16 2016 21:42:11 gcc 4.4.7

문제가 났을 때 어느 빌드인지 물어보면 되고 이것이 없으면 언제 빌드한 것인지 물어도 답이 안 나온다.

각자 자리에서 빌드해서 올리는 방식 자체도 문제라 빌드 서버에서만 만들고 그 결과물을 배포하게 바꿨다. 개발 중에는 각자 빌드하되 배포용은 빌드 서버 것만 쓴다.

echo "$(date +%Y%m%d-%H%M) $(svnversion)" > build/RELEASE

빌드 서버에서 만든 것에 RELEASE 표시를 붙이고 배포 전에 이 파일이 있는지 확인한다. 없으면 개인 빌드다.

빌드 서버를 다시 만들 일이 있을 수 있으니 무엇이 깔려 있는지도 적었다.

빌드 서버 환경

OS       CentOS 6.7
gcc      4.4.7 (기본 저장소)
make     3.81
추가 라이브러리
  - libssl-devel 1.0.1e
  - zlib-devel 1.2.3

버전을 적은 것이 중요했다. 최신이라고 적으면 다시 만들 때 다른 것이 깔린다.

정리


Share this post on:

Previous Post
소셜 동작마다 엔드포인트가 하나씩이었다
Next Post
결제에 상태가 셋이었다