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 |