View | Details | Raw Unified | Return to bug 204577 | Differences between
and this patch

Collapse All | Expand All

(-)Mk2/Uses/nodejs.mk (+303 lines)
Line 0 Link Here
1
# $FreeBSD$
2
#
3
# Provide support for NodeJS based projects
4
#
5
# Feature:	node
6
# Usage:	USES=nodejs
7
#
8
# MAINTAINER: portmgr@FreeBSD.org
9
10
.if !defined(_INCLUDE_USES_NODE_MK)
11
_INCLUDE_USES_NODE_MK=	yes
12
13
FETCH_DEPENDS=	npm:${PORTSDIR}/www/npm
14
BUILD_DEPENDS=	npm:${PORTSDIR}/www/npm \
15
		gmake:${PORTSDIR}/devel/gmake
16
RUN_DEPENDS=	node:${PORTSDIR}/www/node
17
18
.if defined(NODE_MODULES)
19
FETCH_DEPENDS+=	jq:${PORTSDIR}/textproc/jq
20
JQ_CMD=		${LOCALBASE}/bin/jq
21
.endif
22
23
_NODE_DIR?=		${PORTNAME}-${PORTVERSION}
24
25
# commands
26
NPM_CMD=		${LOCALBASE}/bin/npm
27
NODE_CMD=		${LOCALBASE}/bin/node
28
29
# variables
30
_NODE_PROFILE_DIR=	${WRKDIR}/.userprofile
31
_NODE_TMP_DIR=		${WRKDIR}/.tmp
32
_NODE_FAKE_GIT=		${_NODE_TMP_DIR}/fake-git
33
_NODE_FAKE_MAKE=	${_NODE_TMP_DIR}/gmake
34
_NODE_NPMRC=		${_NODE_PROFILE_DIR}/.npmrc
35
CFLAGS+=		-I${LOCALBASE}/include/node
36
CXXFLAGS+=		-I${LOCALBASE}/include/node
37
NPM_ENV+=		HOME=${_NODE_PROFILE_DIR} TMP=${_NODE_TMP_DIR}
38
NPM_ENV+=		PATH=${_NODE_TMP_DIR}:${PATH}
39
NPM_ENV+=		C=${CC} CXX=${CXX}
40
NPM_FETCH_ARGS=		--loglevel warn --ignore-scripts
41
NPM_BUILD_ARGS=		--loglevel warn --nodedir=${LOCALBASE}
42
NPM_PRUNE_ARGS=		--loglevel warn --production=true
43
NPM_SHRINKWRAP_ARGS=	--dev
44
REINPLACE_ARGS=		-i ""
45
SHRINKWRAP_FILE=	${FILESDIR}/npm-shrinkwrap.json
46
NODE_INSTALL_BASE:=	${LOCALBASE}/share/node-projects
47
NODE_INSTALL_DIR:=	${NODE_INSTALL_BASE}/${PORTNAME}
48
NODE_ORIG_DISTFILES:=	${DISTFILES}
49
NODE_DISTFILE:=		${PORTNAME}-${PORTVERSION}-nodejs.tar.gz
50
CKSUMFILES+=		${NODE_DISTFILE}
51
_NODE_MASTER_SITE_BACKUP_URLS= ${MASTER_SITE_BACKUP}${NODE_DISTFILE}
52
53
.if defined(NODE_SRCDIR)
54
_NODE_DO_CD=node_modules/${NODE_SUBDIR}
55
.else
56
_NODE_DO_CD=.
57
.endif
58
_NODE_FETCH_WORKDIR=${DISTDIR}
59
60
makeshrinkwrap: do-fetch
61
	@cd ${_NODE_FETCH_WORKDIR}; \
62
		for distfile in ${NODE_DISTFILE}; do \
63
		  break; \
64
		done; \
65
		${TAR} xzf $$distfile && \
66
		cd ${_NODE_DIR} && \
67
		cd ${_NODE_DO_CD} && \
68
		${NPM_ENV} ${NPM_CMD} shrinkwrap ${NPM_SHRINKWRAP_ARGS} && \
69
		${MKDIR} ${FILESDIR} && \
70
		${MV} npm-shrinkwrap.json ${SHRINKWRAP_FILE} && \
71
		cd ${_NODE_FETCH_WORKDIR} && \
72
		${RM} -r ${_NODE_DIR}
73
74
userprofile_fetch: .EXEC .PHONY
75
	@${RM} -rf ${_NODE_PROFILE_DIR} ${_NODE_TMP_DIR}
76
	@${MKDIR} ${_NODE_PROFILE_DIR} ${_NODE_TMP_DIR}
77
78
userprofile_build: .EXEC .PHONY
79
	@${RM} -rf ${_NODE_PROFILE_DIR} ${_NODE_TMP_DIR}
80
	@${MKDIR} ${_NODE_PROFILE_DIR} ${_NODE_TMP_DIR}
81
82
fakegit: .EXEC .PHONY
83
	@(${ECHO} '#!/bin/sh'; \
84
	${ECHO} ''; \
85
	${ECHO} 'name="nodejs-fetch"'; \
86
	${ECHO} 'DISTDIR="${DISTDIR}"'; \
87
	${ECHO} 'NODE_ORIG_DISTFILES="${NODE_ORIG_DISTFILES:C@^([^:]+).*@\1@}"'; \
88
	${ECHO} 'NODE_VERBOSE="${NODE_VERBOSE}"'; \
89
	${ECHO} 'NODE_DEBUG="${NODE_DEBUG}"'; \
90
	${ECHO} ''; \
91
	${ECHO} 'msg() {'; \
92
	${ECHO} '  [ "$$NODE_VERBOSE" = yes ] && echo "$${name}: $$1" >&2'; \
93
	${ECHO} '  dbg_log "$${name}: $$1"'; \
94
	${ECHO} '}'; \
95
	${ECHO} 'err() {'; \
96
	${ECHO} '  echo "$${name}: ERROR: $$1" >&2'; \
97
	${ECHO} '  dbg_log "$${name}: ERROR: $$1"'; \
98
	${ECHO} '}'; \
99
	${ECHO} 'dbg_log() {'; \
100
	${ECHO} '  [ "$$NODE_DEBUG" = yes ] && (echo "$$1" >>/tmp/nodejs-$$$$.log)'; \
101
	${ECHO} '}'; \
102
	${ECHO} ''; \
103
	${ECHO} 'dbg_log "called with arguments: $$*"'; \
104
	${ECHO} ''; \
105
	${ECHO} 'cmd_clone_remote() {'; \
106
	${ECHO} '  local mirror="$$1"'; \
107
	${ECHO} '  local dir="$$2"'; \
108
	${ECHO} '  msg "Git clone requested: mirror=$$mirror -> dir=$${dir}"'; \
109
	${ECHO} '  local fname_regex=$$(echo $$mirror | sed -E "s/https:\/\/github\.com\/([^/]+)\/([^/]+)\.git$$/^\1-\2-[[:alnum:].]*_GH0.tar.gz$$/g")'; \
110
	${ECHO} '  local fname=$$(find_file "$${fname_regex}")'; \
111
	${ECHO} '  if [ -n "$${fname}" ]; then'; \
112
	${ECHO} '    msg "Found distfile=$$fname for $$mirror"'; \
113
	${ECHO} '    (cd $${dir} && tar xzf $${DISTDIR}/$${fname} --strip 1)'; \
114
	${ECHO} '    return $$?'; \
115
	${ECHO} '  else'; \
116
	${ECHO} '    err "Failed to find distfile for $$mirror"'; \
117
	${ECHO} '    return 1'; \
118
	${ECHO} '  fi'; \
119
	${ECHO} '}'; \
120
	${ECHO} 'cmd_clone_local() {'; \
121
	${ECHO} '  local src="$$1"'; \
122
	${ECHO} '  local dst="$$2"'; \
123
	${ECHO} '  msg "copy $$src -> $$dst"'; \
124
	${ECHO} '  (cd $${src} && tar czf - .) | (cd $${dst} && tar xzf -)'; \
125
	${ECHO} '}'; \
126
	${ECHO} ''; \
127
	${ECHO} 'cmd_checkout() {'; \
128
	${ECHO} '  msg "do nothing for checkout of $$1 in `pwd`"'; \
129
	${ECHO} '}'; \
130
	${ECHO} ''; \
131
	${ECHO} 'find_file() {'; \
132
	${ECHO} '  for f in $${NODE_ORIG_DISTFILES}; do'; \
133
	${ECHO} '    if expr "$${f}" : "$${fname_regex}" > /dev/null; then'; \
134
	${ECHO} '      echo "$$f"'; \
135
	${ECHO} '      return'; \
136
	${ECHO} '    fi'; \
137
	${ECHO} '  done'; \
138
	${ECHO} '}'; \
139
	${ECHO} ''; \
140
	${ECHO} 'case $$1 in'; \
141
	${ECHO} 'clone)'; \
142
	${ECHO} '  shift'; \
143
	${ECHO} '  while [ $$# -gt 0 ]; do'; \
144
	${ECHO} '    key="$$1"'; \
145
	${ECHO} '    case $$key in'; \
146
	${ECHO} '        --template=*)'; \
147
	${ECHO} '      ;;'; \
148
	${ECHO} '      --mirror)'; \
149
	${ECHO} '        MIRROR="$$2"'; \
150
	${ECHO} '        shift'; \
151
	${ECHO} '      ;;'; \
152
	${ECHO} '      -*)'; \
153
	${ECHO} '        err "Unknown argument: $$key" && exit 1'; \
154
	${ECHO} '      ;;'; \
155
	${ECHO} '      *)'; \
156
	${ECHO} '        if [ $$# -eq 1 -a -n "$$MIRROR" ]; then'; \
157
	${ECHO} '          cmd_clone_remote "$${MIRROR}" "$$key"'; \
158
	${ECHO} '          exit $$?'; \
159
	${ECHO} '        fi'; \
160
	${ECHO} '        if [ $$# -eq 2 -a -z "$$MIRROR" ]; then'; \
161
	${ECHO} '          cmd_clone_local "$$1" "$$2"'; \
162
	${ECHO} '          exit $$?'; \
163
	${ECHO} '        fi'; \
164
	${ECHO} '        err "Unknown argument #=$$#: $$key"'; \
165
	${ECHO} '        exit 1'; \
166
	${ECHO} '      ;;'; \
167
	${ECHO} '    esac'; \
168
	${ECHO} '    shift'; \
169
	${ECHO} '  done'; \
170
	${ECHO} '  ;;'; \
171
	${ECHO} 'rev-list)'; \
172
	${ECHO} '  shift'; \
173
	${ECHO} '  while [ $$# -gt 0 ]; do'; \
174
	${ECHO} '    key="$$1"'; \
175
	${ECHO} '    case $$key in'; \
176
	${ECHO} '      -n1)'; \
177
	${ECHO} '        shift'; \
178
	${ECHO} '        [ $$# -eq 1 ] || ! err "Unknown argument: $$key" || exit 1'; \
179
	${ECHO} '        msg "Returning same revision $$1"'; \
180
	${ECHO} '        echo $$1'; \
181
	${ECHO} '        exit 0'; \
182
	${ECHO} '      ;;'; \
183
	${ECHO} '      *)'; \
184
	${ECHO} '        err "Unknown argument: $$key" && exit 1'; \
185
	${ECHO} '      ;;'; \
186
	${ECHO} '    esac'; \
187
	${ECHO} '    shift'; \
188
	${ECHO} '  done'; \
189
	${ECHO} '  err "rev-list without arguments" && exit 1'; \
190
	${ECHO} '  ;;'; \
191
	${ECHO} 'checkout)'; \
192
	${ECHO} '  shift'; \
193
	${ECHO} '  if [ $$# -eq 1 ]; then'; \
194
	${ECHO} '    cmd_checkout "$$1"'; \
195
	${ECHO} '    exit 0'; \
196
	${ECHO} '  fi'; \
197
	${ECHO} '  ;;'; \
198
	${ECHO} '*)'; \
199
	${ECHO} '  err "Unknown command: $$1" && exit 1'; \
200
	${ECHO} '  ;;'; \
201
	${ECHO} 'esac'; \
202
	${ECHO} '') >> ${_NODE_FAKE_GIT}
203
	@${CHMOD} +x ${_NODE_FAKE_GIT}
204
	@${ECHO} "git = ${_NODE_FAKE_GIT}" >> ${_NODE_NPMRC}
205
206
fakemake: .EXEC .PHONY
207
	@(${ECHO} '#!/bin/sh'; \
208
	${ECHO} ''; \
209
	${ECHO} '${MAKE_ENV} PATH=$$PATH:${LOCALBASE}/bin ${LOCALBASE}/bin/gmake ${MAKE_ARGS} $$@'; \
210
	${ECHO} '') >> ${_NODE_FAKE_MAKE}
211
	@${CHMOD} +x ${_NODE_FAKE_MAKE}
212
 
213
post-fetch: userprofile_fetch fakegit
214
	@${MKDIR} ${_NODE_FETCH_WORKDIR}
215
	@cd ${_NODE_FETCH_WORKDIR}; \
216
		for main_distfile in ${NODE_ORIG_DISTFILES}; do \
217
		  break; \
218
		done; \
219
		force_fetch=false; \
220
		for afile in ${FORCE_FETCH}; do \
221
		  afile=$${afile##*/}; \
222
		  if [ "x$$afile" = "x${NODE_DISTFILE}" ]; then \
223
		    force_fetch=true; \
224
		  fi; \
225
		done; \
226
		if [ ! -f ${NODE_DISTFILE} -o "$$force_fetch" = "true" ]; then \
227
		        ${RM} -rf ${_NODE_PROJECT_FILE} ${_NODE_DIR} ${NODE_DISTFILE}; \
228
		        for url in ${_NODE_MASTER_SITE_BACKUP_URLS}; do \
229
		          if ${ECHO_MSG} "=> Attempting to fetch ${PORTNAME} from the master backup site" && \
230
		             ${SETENV} ${FETCH_ENV} ${FETCH_CMD} ${FETCH_BEFORE_ARGS} $${url} ${FETCH_AFTER_ARGS}; then \
231
		             return 0; \
232
		        fi; \
233
		        done; \
234
		        if ${ECHO_MSG} "=> Extracting node project source (in `pwd`)" && \
235
		           ${EXTRACT_CMD} ${EXTRACT_BEFORE_ARGS} $${main_distfile} ${EXTRACT_AFTER_ARGS} && \
236
		           ${ECHO_MSG} "=> Preparing the node project (in `pwd`)" && \
237
		           cd ${_NODE_DIR} && \
238
		           ([ -z "${NODE_SRCDIR}" ] || \
239
		              (${MKDIR} node_modules && \
240
		               ${MV} ${NODE_SRCDIR} node_modules/${NODE_SUBDIR} \
241
		              ) \
242
		           ) && cd ${_NODE_DO_CD} && \
243
		           for m in ${NODE_MODULES}; do \
244
		             ${JQ_CMD} -s ".[0] * `${ECHO} $${m} | ${SED} -E 's/([[:alnum:]]+):([[:digit:].]+)/{"dependencies":{"\1":"\2"}}/'`" \
245
		               package.json > package-new.json && ${MV} package-new.json package.json; \
246
		           done && \
247
		           ([ -f "${SHRINKWRAP_FILE}" ] || \
248
		            ${ECHO} "Warning: no shrinkwrap file, you need to run 'make makeshrinkwrap'" >&2) && \
249
		           ([ ! -f "${SHRINKWRAP_FILE}" ] || \
250
		            ${CP} ${SHRINKWRAP_FILE} npm-shrinkwrap.json) && \
251
		           ${ECHO_MSG} "=> Downloading the project dependencies (in `pwd`)" && \
252
		           ${NPM_ENV} ${NPM_CMD} install ${NPM_FETCH_ARGS} && \
253
		           cd ${_NODE_FETCH_WORKDIR} && \
254
		           ${FIND} ${_NODE_DIR} -and -exec ${TOUCH} -h -d 1970-01-01T00:00:00Z {} + && \
255
		           ${FIND} ${_NODE_DIR} -print0 | sort -z | \
256
		                ${TAR} czf ${NODE_DISTFILE} --options gzip:!timestamp --no-recursion --null -T - && \
257
		           ${RM} -rf ${_NODE_DIR}; then \
258
		           return 0; \
259
		        fi; \
260
		        ${ECHO_MSG} "=> Fetch failed for ${PORTNAME}"; \
261
		        exit 1; \
262
		fi;
263
264
do-extract:
265
	@cd ${WRKDIR} && \
266
		tar xzf ${DISTDIR}/${NODE_DISTFILE}
267
268
post-patch:
269
	@${FIND} ${WRKSRC} -name "*.gyp" -and -exec ${REINPLACE_CMD} -e "s|cflags': \[|cflags': ['-I${LOCALBASE}/include/node',|g" {} \;
270
271
npm-build: userprofile_build fakemake
272
	@cd ${WRKSRC} && \
273
		cd ${_NODE_DO_CD} && \
274
		${NPM_ENV} ${NPM_CMD} rebuild ${NPM_BUILD_ARGS}
275
276
npm-prune:
277
	@cd ${WRKSRC} && \
278
		cd ${_NODE_DO_CD} && \
279
		${NPM_ENV} ${NPM_CMD} prune ${NPM_PRUNE_ARGS}
280
281
do-build: npm-build npm-prune
282
283
post-build:
284
	@${ECHO} "Deleting created .pyc files that npm should have installed"
285
	@${RM} -rf `${FIND} ${LOCALBASE}/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp -name "*.pyc"`
286
287
do-install:
288
	@${ECHO} "=> Staging ${PKGNAME}"
289
	@${MKDIR} ${STAGEDIR}${NODE_INSTALL_BASE}
290
	@${CP} -r ${WRKSRC} ${STAGEDIR}${NODE_INSTALL_DIR}
291
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name Makefile`
292
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.bat"`
293
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.log"`
294
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.orig"`
295
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.bak"`
296
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name ".git*"`
297
	@${RM} `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name npm-shrinkwrap.json`
298
	@${RM} -rf `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name Release`
299
	@${RM} -rf `${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name .deps`
300
	@${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.o" -and -exec ${STRIP_CMD} {} \;
301
	@${FIND} ${STAGEDIR}${NODE_INSTALL_DIR} -name "*.node" -and -exec ${STRIP_CMD} {} \;
302
303
.endif

Return to bug 204577