summaryrefslogtreecommitdiff
blob: 3170c7364f9e194e0ff89ac3d3ca0f003659c622 (plain)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/ccc.eclass,v 1.21 2009/02/08 17:16:02 vapier Exp $

# @ECLASS: ccc.eclass
# @MAINTAINER:
# alpha@gentoo.org
# @BLURB: functions to make ebuilds more ccc friendly.
#
# Authors:
# Tavis Ormandy <taviso@gentoo.org>
# Aron Griffis <agriffis@gentoo.org>

inherit flag-o-matic

# define this to make this eclass noisy.
#DEBUG_CCC_ECLASS=1

ccc-fixup()
{
	# helper function to fixup files
	# and show differences when debugging
	#
	# store the backup suffix.
	local files list suffix=ccc-fixup-${$}

	while read files
	do
		sed --in-place=.${suffix} ${1} ${files} || return 1
		list="${list} ${files}"
	done

	[ ! "$DEBUG_CCC_ECLASS" ] && return 0
	# if theres a backup, diff it.
	for i in ${list}
	do
		einfo "Checking for changes to `basename ${i}` ..."
		if [ -e "${i}.${suffix}" ]; then
			diff -u ${i}.${suffix} ${i}
#			sleep 1
		fi
	done
}

# @FUNCTION: hide-restrict-arr
# @DESCRIPTION:
# Scan for and replace __restrict_arr with a ccc
# supported equivalent.
#
# You might see an error like this if you need this:
# @CODE
# 	cc: Error: regexec.c, line 209: In the definition of the function "regexec",
# 	the promoted type of pmatch is incompatible with the type of the corresponding
# 	parameter in a prior declaration. (promotmatch)
# 	    regmatch_t pmatch[];
# 	    ---------------^
# @CODE
hide-restrict-arr()
{
	# __restrict_arr causes trouble with ccc, __restrict
	# is a supported equivalent.
	#
	# example:
	#           regmatch_t __pmatch[__restrict_arr]
	#

	find ${WORKDIR} -iname '*.h' | \
		xargs | ccc-fixup 's#\(\[__restrict\)_arr\]#\1\]#g'
}

# @FUNCTION: replace-cc-hardcode
# @DESCRIPTION:
# Look for common cc hardcodes in Makefiles.
replace-cc-hardcode()
{
	# lots of developers hardcode gcc into their
	# Makefiles. Try and fix these.
	#
	find ${WORKDIR} -iname Makefile | \
		xargs | ccc-fixup "s#^\(CC.*=\).*g\?cc#\1${CC:-gcc}#g"
}

# @FUNCTION: replace-cxx-hardcode
# @DESCRIPTION:
# Look for common cxx hardcodes in Makefiles.
replace-cxx-hardcode()
{
	# lots of developers hardcode g++ into thier
	# Makefiles. Try and fix these.
	find ${WORKDIR} -iname Makefile | \
		xargs | ccc-fixup "s#^\(CXX.*=\).*[gc]\{1\}++#\1${CXX:-g++}#g"
}

# @FUNCTION: is-ccc
# @RETURN: Returns success if dec compiler is being used.
# @DESCRIPTION:
# example:
#
# 	is-ccc && hide-restrict-arr
is-ccc()
{
	# return true if ccc is being used.
	[ "${ARCH}:`basename ${CC:-gcc}`" == "alpha:ccc" ]
}

# @FUNCTION: is-cxx
# @RETURN: Returns success if dec c++ compiler is being used.
is-cxx()
{
	# return true if cxx is being used
	[ "${ARCH}:`basename ${CXX:-g++}`" == "alpha:cxx" ]
}

# @FUNCTION: replace-ccc-g
# @DESCRIPTION:
# Try to replace -g with -g3
replace-ccc-g()
{
	# -g will stop ccc/cxx performing optimisation
	# replacing it with -g3 will let them co-exist.
	find ${WORKDIR} -iname Makefile | \
		xargs | ccc-fixup \
		"s#\(^\CX\{,2\}FLAGS[[:space:]]*=.*[\'\"\x20\t]*\)-g\([\'\"\x20\t]\|$\)#\1-g3\2#g"
	# FIXME: my eyes! it burns!
}

# @FUNCTION: ccc-elf-check
# @RETURN: Return success if binary was compiled with ccc
# @DESCRIPTION:
# example:
# @CODE
# 	if ! is-ccc; then
# 		ccc-elf-check /usr/lib/libglib.a && \
# 			append-ldflags -lots
# 	fi
# @CODE
#
# NOTE: i think the binary and shared library detection
# is pretty safe, but the archive detection may not
# be as reliable.
ccc-elf-check()
{
	# check if argument is a ccc created executable.
	# this is useful for libraries compiled with ccc,
	# which might require -lots/-lcpml if a linking binary
	# isnt being compiled with ccc.
	local myBINARY=${1:-a.out}
	if [[ ! "${myBINARY}" == *.a ]]; then
		# find the offset and size of the elf .note section.
		# example contents: 000132d2 00000dc8
		#                   ^- offset ^- size
		local elf_note_offset=`objdump -h ${myBINARY} | \
		grep -E '^\ [0-9]{2,}\ .note\ ' | \
			awk '{print $6,$3}' | \
			line`
		# check if that got anything.
		[ ! "${elf_note_offset}" ] && return 1
		# dump contents of section, and check for compaq signature.
		hexdump -s 0x${elf_note_offset% *} -n $((0x${elf_note_offset#* })) -e '"%_p"' ${myBINARY} | \
			grep -E 'Compaq Computer Corp.' &>/dev/null && return 0
		# no compaq message, return 1
	else
		# just grep it for the Compaq sig.
		hexdump -e '"%_p"' ${myBINARY} | \
			grep -E 'Compaq Computer Corp.' &>/dev/null && return 0
	fi
	return 1
}

# @FUNCTION: create-so
# @USAGE: < /usr/lib/library.a > < library.so >
# @DESCRIPTION:
# Make the shared library (.so) specified from the archive (.a)
# specified. LDFLAGS will be honoured. if you need a different
# `soname` (DT_SONAME) from the shared lib filename, you will have
# to do it manually ;)
#
# example:
# @CODE
# 	is-ccc && \
# 		create-so /usr/lib/libcoolstuff.a libcoolstuff.so.${PV}
# 	dosym /usr/lib/libcoolstuff.so.${PV} /usr/lib/libcoolstuff.so
# @CODE
#
# NOTE: -lots will be used by default, this is ccc.eclass after all :)
# NOTE: .${PV} is optional, of course.
# NOTE: dolib.so will manage installation
create-so()
{
	# some applications check for .so, but ccc wont
	# create one by default
	if [[ "${2}" == *.so ]]; then
	# no version suffix.
		${LD:-ld} -shared -o ${T}/${2##*/} -soname ${2##*/} \
			-whole-archive ${1} -no-whole-archive -lots ${LDFLAGS}
	else
	# version suffix
		local so_version=${2##*.so}
		${LD:-ld} -shared -o ${T}/${2##*/} -soname `basename ${2/${so_version}}` \
				-whole-archive ${1} -no-whole-archive -lots ${LDFLAGS}
	fi
	# hand installation over to dolib.so
	dolib.so ${T}/${2##*/}
}

# @FUNCTION: otsify
# @USAGE: < archive >
# @DESCRIPTION:
# Add the functions from libots to <archive>, this means
# that if you use gcc to build an application that links with
# <archive>, you wont need -lots.
# Use this on libraries that you want maximum performance from,
# but might not be using ccc when linking against it (eg zlib, openssl, etc)
#
# example:
# 
# 	is-ccc && otsify ${S}/libz.a
otsify()
{
	[ "$DEBUG_CCC_ECLASS" ] && local ar_args="v"

	# confirm argument exists, and is an archive (eg *.a)
	# if it is, extract libots members into tempdir, then
	# append them to argument, regenerate index and then return.

	if [ "${1##*.}" == "a" ] && [ -f "${1}" ]; then
		einfo "otsifying `basename ${1}` ..."

		mkdir ${T}/ccc-otsify-${$}
		cd ${T}/ccc-otsify-${$}

		einfo "	extracting archive members from libots ..."
		ar ${ar_args}x /usr/lib/libots.a || {
			eerror "	unable to extract libots members."
			return 1
		}

		einfo "	appending libots members to `basename ${1}` ..."
		ar ${ar_args}q ${1} ${T}/ccc-otsify-${$}/*.o || {
			eerror "	failed to append libots members to ${1}."
			return 1
		}

		einfo  "	regenerating `basename ${1}` archive index ..."
		ranlib ${1} || ewarn "	ranlib returned an error, probably not important."
		einfo "otsification completed succesfully."
		cd ${OLDPWD:-.}
		return 0
	else
		ewarn "called otsify() with bad argument ..."
		cd ${OLDPWD:-.}
		return 1
	fi
}