C 과제의 경우 Makefile
, C 파일, 헤더 파일 정도만 제출할 수 있습니다.
기본적인 .gitignore
나 .editorconfig
조차 제출하면 안 됩니다.
당연히 .vscode
같은 에디터 설정 파일도 제출할 수 없습니다.
<aside>
💡 .gitignore
나 .editorconfig
같은 파일들도 Git 저장소에 올리는 게 국룰입니다.
심지어 vscode가 유용한 프로젝트라면 .vscode
조차요!
</aside>
실제로 소스 폴더를 건드리는 것은 소스 파일을 건드리는 것과 다를 게 없지만,
Norm에서는 Makefile에 모든 소스 파일이 명시적으로 드러날 것을 요구하고 있습니다.
그래서 wildcard를 쓸 수 없습니다. ????????????????? ❓ ❔ ⁉️ 😒
일단 문제 해결 전에 유틸 변수들을 만들어둘게요
Q := $(if $(filter 1,$(V) $(VERBOSE)),,@)
MAKE := make $(if $(filter 1,$(V) $(VERBOSE)),,--no-print-directory)
make
명령이 너무 많은 것을 출력하지 않도록 하기 위해 V
와 MAKE
변수를 사용할 거에요.
make V=1 all
처럼 V
나 VERBOSE
를 1로 설정하면 원래대로 전체 로그를 볼 수 있어요.
꼭 필요한 파일만 제출하라고 해서, 여러분의 개발환경을 망치지 마세요.
여러분의 생산성은 소중합니다.
소스 파일을 저장소 루트 디렉터리에 두면 제출하기가 힘들어집니다.
이 셋 중에 하나를 선택해야 하는데, 다 수동으로 하기에는 여간 귀찮은 게 아니죠.
소스 파일을 src
디렉터리에 두고 작업하는 경우를 예로 들어볼게요
# ... 중략
test:
$Q$(MAKE) -C test test
publish_without_test:
ifndef GIT_REMOTE_URL
$(error GIT_REMOTE_URL is undefined)
endif
$Qcp -r ./src ./tmp
$Q$(MAKE) -C tmp fclean
$Q(cd tmp && git init && git add . && git commit -m "Initial commit" && git push "$(GIT_REMOTE_URL)" HEAD:master)
$Qrm -rf tmp
$Qgit push "$(GIT_REMOTE_URL)" HEAD:source || echo "Failed to push HEAD to source"
publish: test publish_without_test
.PHONY: test publish_without_test publish
저장소 루트의 Makefile
일부입니다.
src
에 제출할 파일이 있는 것처럼, test
에 테스트용 파일이 있다고 가정합니다.이제 제출하려면 make GIT_REMOTE_URL=(저장소 주소) publish
를 입력하면 됩니다.
publish
명령어를 실행하면 대충 아래와 같은 일이 일어납니다.
src
를 tmp
로 복사하고, make fclean
을 통해 임시 파일을 모두 삭제합니다.tmp
에서 git 저장소 초기화, 커밋 후 주어진 저장소의 master
브랜치에 push합니다.HEAD
)를 주어진 저장소의 source
브랜치에 push합니다.
기계채점은 master
에서 진행될 것이고, source
는 동료평가에서 큰 도움이 될 것입니다.이제 src
가 아닌 저장소 루트 디렉터리에서 .gitignore
, .editorconfig
등을 사용할 수 있습니다!
publish_without_test:
ifndef GIT_REMOTE_URL
$(error GIT_REMOTE_URL is undefined)
endif
$Qcp -r ./src ./tmp
$Q$(MAKE) -C tmp fclean
$Qprintf "# script-generated file list\\nSRCS := %s\\n\\n" "$$(cd src && find . -name "*.c" | cut -c 3- | xargs)" | cat - src/Makefile > tmp/Makefile
$Q(cd tmp && git init && git add . && git commit -m "Initial commit" && git push "$(GIT_REMOTE_URL)" HEAD:master
$Qrm -rf tmp
$Qgit push "$(GIT_REMOTE_URL)" HEAD:source || echo "Failed to push HEAD to source"
publish
스크립트에 한 줄을 추가했습니다.
printf "# script-generated file list\\nSRCS := %s\\n\\n" "$(cd src && find . -name "*.c" | cut -c 3- | xargs)" | cat - src/Makefile > tmp/Makefile
커밋하기 전에 제출할 Makefile
의 첫 부분에 소스 파일의 목록을 넣는 스크립트입니다.
src/Makefile
(제출할 Makefile
)에서는 아래처럼 작성할 수 있습니다.
# This variable will be used only if source files are not hardcoded
SRCS ?= $(wildcard *.c)
# ... 또는 (저장소 루트가 아닌 다른 디렉터리에 소스 파일이 있는 경우)
SRCS ?= $(shell find . -name "*.c" | cut -c 3-)
제출한 파일에는 SRCS
가 있기 때문에 제출한 파일에서는 wildcard가 사용되지 않습니다.
이렇게 하면 소스 파일을 이중 삼중으로 관리하는 끔찍한 노가다를 피할 수 있습니다.
src/Makefile
) - 프로젝트마다 다름 - 일부Q := $(if $(filter 1,$(V) $(VERBOSE)),,@)
MAKE := make $(if $(filter 1,$(V) $(VERBOSE)),,--no-print-directory)
# This variable will be used only if source files are not hardcoded
SRCS ?= $(shell find . -name "*.c" | cut -c 3-)
# 주의! 프로젝트마다 바꿀 것
NAME := libft.a
all: $(NAME)
clean:
$Qfind -type f -a \\( -name "*.o" -o -name "*.d" -delete \\)
fclean: clean
$Qrm -f $(NAME)
re:
$Q$(MAKE) fclean
$Q$(MAKE) all
.PHONY: all clean fclean re
CC := clang
CFLAGS := -Wall -Wextra -Werror
DEPS := $(SRCS:.c=.d)
-include $(DEPS)
%.o: %.c
$Q$(CC) $(CFLAGS) -c $< -o $@ -MMD
# 프로젝트마다 필요한 것들. 그냥 예시
SRCS_BASIC := $(filter-out $(filter %_bonus.c,$(SRCS)), $(SRCS))
# ...후략
Q := $(if $(filter 1,$(V) $(VERBOSE)),,@)
MAKE := make $(if $(filter 1,$(V) $(VERBOSE)),,--no-print-directory)
all: test
clean:
$Qrm -rf ./tmp
$Q$(MAKE) -C src clean
$Q$(MAKE) -C test clean
fclean: clean
$Q$(MAKE) -C src fclean
$Q$(MAKE) -C test fclean
re:
$Q$(MAKE) -C src fclean
$Q$(MAKE) test
test:
$Q$(MAKE) -C test test
publish_without_test:
ifndef GIT_REMOTE_URL
$(error GIT_REMOTE_URL is undefined)
endif
$Qcp -r ./src ./tmp
$Q$(MAKE) -C tmp fclean
$Qprintf "# script-generated file list\\nSRCS := %s\\n\\n" "$$(cd src && find . -name "*.c" | cut -c 3- | xargs)" | cat - src/Makefile > tmp/Makefile
$Q(cd tmp && git init && git add . && git commit -m "Initial commit" && git push "$(GIT_REMOTE_URL)" HEAD:master
$Qrm -rf tmp
$Qgit push "$(GIT_REMOTE_URL)" HEAD:source || echo "Failed to push HEAD to source"
publish: test publish_without_test
.PHONY: all clean fclean re test publish publish_without_test