merge 5.1.0-release
commit
d7c8678c3a
|
|
@ -17,6 +17,8 @@ build-darwin-*
|
|||
build-vc80/
|
||||
build-vc100/
|
||||
build-vc120/
|
||||
build-vc120-32/
|
||||
build-vc120-64/
|
||||
indra/build-vc[0-9]*
|
||||
indra/CMakeFiles
|
||||
indra/lib/mono/1.0/*.dll
|
||||
|
|
|
|||
1
.hgtags
1
.hgtags
|
|
@ -531,3 +531,4 @@ b4d76b5590fdf8bab72c64442353753a527cbc44 5.0.5-release
|
|||
abcab37e1b29414ab8c03af9ca2ab489d809788a 5.0.7-release
|
||||
505a492f30bd925bb48e2e093ae77c3c2b4c740f 5.0.8-release
|
||||
40ca7118765be85a043b31b011e4ee6bd9e33c95 5.0.9-release
|
||||
ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release
|
||||
|
|
|
|||
28
BuildParams
28
BuildParams
|
|
@ -3,36 +3,18 @@
|
|||
# Please refer to:
|
||||
# https://wiki.secondlife.com/wiki/Automated_Build_System
|
||||
|
||||
|
||||
# Global setting for now....
|
||||
Darwin.symbolfiles = "newview/Release/secondlife-symbols-darwin.tar.bz2"
|
||||
CYGWIN.symbolfiles = "newview/Release/secondlife-symbols-windows.tar.bz2"
|
||||
Linux.symbolfiles = "newview/secondlife-symbols-linux.tar.bz2"
|
||||
# Variants (NOTE: 'Release' must be last for uploads to work correctly)
|
||||
variants = "RelWithDebInfo Release"
|
||||
|
||||
# Use Public Upload Locations
|
||||
public_build = true
|
||||
build_docs = true
|
||||
|
||||
# disable all Debug builds (RelWithDebInfo is sufficient)
|
||||
build_CYGWIN_Debug = false
|
||||
build_Linux_Debug = false
|
||||
build_Darwin_Debug = false
|
||||
build_Debug = false
|
||||
|
||||
# enable Doxygen building on Linux for TeamCity (it can be done manually on any platform)
|
||||
build_Linux_Doxygen = true
|
||||
|
||||
# Update Public Inworld Build Status Indicators (setting should mirror "public_build")
|
||||
email_status_this_is_os = true
|
||||
|
||||
# Limit extent of codeticket updates to revisions after...
|
||||
codeticket_since = 3.3.0-release
|
||||
|
||||
# Override build system default toolchain
|
||||
# Note that this will only affect automated builds.
|
||||
Linux.distcc_version =
|
||||
Linux.gcc_version = /usr/bin/gcc-4.6
|
||||
Linux.cxx_version = /usr/bin/g++-4.6
|
||||
# Need viewer-build-variables as well as other shared repositories
|
||||
buildscripts_shared_more_NAMEs="build_secrets build_variables"
|
||||
|
||||
################################################################
|
||||
#### Examples of how to set the viewer_channel ####
|
||||
|
|
@ -88,5 +70,5 @@ EDU_viewer_channel_suffix = "edu"
|
|||
# Notifications - to configure email notices use the TeamCity parameter
|
||||
# setting screen for your project or build configuration to set the
|
||||
# environment variable 'email' to a space-separated list of email addresses
|
||||
|
||||
email=""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Second Life Viewer
|
||||
====================
|
||||
|
||||
|
||||
This project manages the source code for the
|
||||
[Second Life](https://www.secondlife.com) Viewer.
|
||||
|
||||
|
|
@ -14,4 +14,3 @@ To download the current default version, visit
|
|||
[the download page](https://secondlife.com/support/downloads). For
|
||||
even newer versions try
|
||||
[the Alternate Viewers page](https://wiki.secondlife.com/wiki/Linden_Lab_Official:Alternate_Viewers)
|
||||
|
||||
|
|
|
|||
2057
autobuild.xml
2057
autobuild.xml
File diff suppressed because it is too large
Load Diff
190
build.sh
190
build.sh
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This is the custom build script for the viewer
|
||||
#
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
build_dir_Darwin()
|
||||
{
|
||||
echo build-darwin-i386
|
||||
echo build-darwin-x86_64
|
||||
}
|
||||
|
||||
build_dir_Linux()
|
||||
|
|
@ -28,7 +28,7 @@ build_dir_Linux()
|
|||
|
||||
build_dir_CYGWIN()
|
||||
{
|
||||
echo build-vc120
|
||||
echo build-vc120-${AUTOBUILD_ADDRSIZE}
|
||||
}
|
||||
|
||||
viewer_channel_suffix()
|
||||
|
|
@ -47,8 +47,8 @@ viewer_channel_suffix()
|
|||
installer_Darwin()
|
||||
{
|
||||
local package_name="$1"
|
||||
local package_dir="$(build_dir_Darwin ${last_built_variant:-Release})/newview/"
|
||||
local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_i386\\.dmg\$"
|
||||
local package_dir="$(build_dir_Darwin)/newview/"
|
||||
local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_x86_64\\.dmg\$"
|
||||
# since the additional packages are built after the base package,
|
||||
# sorting oldest first ensures that the unqualified package is returned
|
||||
# even if someone makes a qualified name that duplicates the last word of the base name
|
||||
|
|
@ -59,7 +59,7 @@ installer_Darwin()
|
|||
installer_Linux()
|
||||
{
|
||||
local package_name="$1"
|
||||
local package_dir="$(build_dir_Linux ${last_built_variant:-Release})/newview/"
|
||||
local package_dir="$(build_dir_Linux)/newview/"
|
||||
local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_i686\\.tar\\.bz2\$"
|
||||
# since the additional packages are built after the base package,
|
||||
# sorting oldest first ensures that the unqualified package is returned
|
||||
|
|
@ -95,14 +95,27 @@ pre_build()
|
|||
&& [ -r "$master_message_template_checkout/message_template.msg" ] \
|
||||
&& template_verifier_master_url="-DTEMPLATE_VERIFIER_MASTER_URL=file://$master_message_template_checkout/message_template.msg"
|
||||
|
||||
"$autobuild" configure "${autobuild_configure_verbosity:---quiet}" -c $variant -- \
|
||||
# nat 2016-12-20: disable HAVOK on Mac until we get a 64-bit Mac build.
|
||||
RELEASE_CRASH_REPORTING=ON
|
||||
HAVOK=ON
|
||||
SIGNING=()
|
||||
if [ "$arch" == "Darwin" ]
|
||||
then
|
||||
if [ "$variant" == "Release" ]
|
||||
then SIGNING=("-DENABLE_SIGNING:BOOL=YES" \
|
||||
"-DSIGNING_IDENTITY:STRING=Developer ID Application: Linden Research, Inc.")
|
||||
fi
|
||||
fi
|
||||
|
||||
-DPACKAGE:BOOL=ON \
|
||||
-DUNATTENDED:BOOL=ON \
|
||||
-DRELEASE_CRASH_REPORTING:BOOL=ON \
|
||||
-DVIEWER_CHANNEL:STRING="\"$viewer_channel\"" \
|
||||
-DHAVOK:BOOL="$HAVOK" \
|
||||
-DRELEASE_CRASH_REPORTING:BOOL="$RELEASE_CRASH_REPORTING" \
|
||||
-DVIEWER_CHANNEL:STRING="${viewer_channel}" \
|
||||
-DGRID:STRING="\"$viewer_grid\"" \
|
||||
-DLL_TESTS:BOOL="$run_tests" \
|
||||
-DTEMPLATE_VERIFIER_OPTIONS:STRING="$template_verifier_options" $template_verifier_master_url \
|
||||
"${SIGNING[@]}" \
|
||||
|| fatal "$variant configuration failed"
|
||||
|
||||
end_section "Configure $variant"
|
||||
|
|
@ -112,21 +125,21 @@ package_llphysicsextensions_tpv()
|
|||
{
|
||||
begin_section "PhysicsExtensions_TPV"
|
||||
tpv_status=0
|
||||
if [ "$variant" = "Release" ]
|
||||
# nat 2016-12-21: without HAVOK, can't build PhysicsExtensions_TPV.
|
||||
if [ "$variant" = "Release" -a "${HAVOK:-}" != "OFF" ]
|
||||
then
|
||||
llpetpvcfg=$build_dir/packages/llphysicsextensions/autobuild-tpv.xml
|
||||
"$autobuild" build "${autobuild_build_verbosity:---quiet}" --config-file $llpetpvcfg -c Tpv
|
||||
test -r "$build_dir/packages/llphysicsextensions/autobuild-tpv.xml" || fatal "No llphysicsextensions_tpv autobuild configuration found"
|
||||
tpvconfig=$(native_path "$build_dir/packages/llphysicsextensions/autobuild-tpv.xml")
|
||||
"$autobuild" build --quiet --config-file "$tpvconfig" -c Tpv || fatal "failed to build llphysicsextensions_tpv"
|
||||
|
||||
# capture the package file name for use in upload later...
|
||||
PKGTMP=`mktemp -t pgktpv.XXXXXX`
|
||||
trap "rm $PKGTMP* 2>/dev/null" 0
|
||||
"$autobuild" package --quiet --config-file $llpetpvcfg --results-file "$(native_path $PKGTMP)"
|
||||
"$autobuild" package --quiet --config-file "$tpvconfig" --results-file "$(native_path $PKGTMP)" || fatal "failed to package llphysicsextensions_tpv"
|
||||
tpv_status=$?
|
||||
if [ -r "${PKGTMP}" ]
|
||||
then
|
||||
cat "${PKGTMP}" >> "$build_log"
|
||||
eval $(cat "${PKGTMP}") # sets autobuild_package_{name,filename,md5}
|
||||
autobuild_package_filename="$(shell_path "${autobuild_package_filename}")"
|
||||
. "${PKGTMP}" # sets autobuild_package_{name,filename,md5}
|
||||
echo "${autobuild_package_filename}" > $build_dir/llphysicsextensions_package
|
||||
fi
|
||||
else
|
||||
|
|
@ -142,10 +155,14 @@ build()
|
|||
local variant="$1"
|
||||
if $build_viewer
|
||||
then
|
||||
begin_section "autobuild $variant"
|
||||
"$autobuild" build --no-configure -c $variant || fatal "failed building $variant"
|
||||
echo true >"$build_dir"/build_ok
|
||||
end_section "autobuild $variant"
|
||||
|
||||
begin_section "extensions $variant"
|
||||
# Run build extensions
|
||||
if [ $build_ok -eq 0 -a -d ${build_dir}/packages/build-extensions ]
|
||||
if [ -d ${build_dir}/packages/build-extensions ]
|
||||
then
|
||||
for extension in ${build_dir}/packages/build-extensions/*.sh
|
||||
do
|
||||
|
|
@ -157,10 +174,10 @@ build()
|
|||
|
||||
# *TODO: Make this a build extension.
|
||||
package_llphysicsextensions_tpv || fatal "failed building llphysicsextensions packages"
|
||||
end_section "extensions $variant"
|
||||
|
||||
echo true >"$build_dir"/build_ok
|
||||
else
|
||||
echo "Skipping build due to configuration build_viewer=${build_viewer}"
|
||||
record_event "Skipping build due to configuration build_viewer=${build_viewer}"
|
||||
echo true >"$build_dir"/build_ok
|
||||
fi
|
||||
}
|
||||
|
|
@ -176,13 +193,9 @@ then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Check to see if we're skipping the platform
|
||||
if ! eval '$build_'"$arch"
|
||||
then
|
||||
record_event "building on architecture $arch is disabled"
|
||||
pass
|
||||
fi
|
||||
initialize_build # provided by master buildscripts build.sh
|
||||
|
||||
begin_section "autobuild initialize"
|
||||
# ensure AUTOBUILD is in native path form for child processes
|
||||
AUTOBUILD="$(native_path "$AUTOBUILD")"
|
||||
# set "$autobuild" to cygwin path form for use locally in this script
|
||||
|
|
@ -194,7 +207,17 @@ then
|
|||
fi
|
||||
|
||||
# load autobuild provided shell functions and variables
|
||||
eval "$("$autobuild" --quiet source_environment)"
|
||||
"$autobuild" --quiet source_environment > "$build_log_dir/source_environment"
|
||||
PYTHONPATH="$BUILDSCRIPTS_SHARED/packages/lib/python:$PYTHONPATH"
|
||||
begin_section "dump source environment commands"
|
||||
cat "$build_log_dir/source_environment"
|
||||
end_section "dump source environment commands"
|
||||
|
||||
begin_section "execute source environment commands"
|
||||
. "$build_log_dir/source_environment"
|
||||
end_section "execute source environment commands"
|
||||
|
||||
end_section "autobuild initialize"
|
||||
|
||||
# something about the additional_packages mechanism messes up buildscripts results.py on Linux
|
||||
# since we don't care about those packages on Linux, just zero it out, yes - a HACK
|
||||
|
|
@ -203,10 +226,9 @@ then
|
|||
export additional_packages=
|
||||
fi
|
||||
|
||||
# dump environment variables for debugging
|
||||
begin_section "Environment"
|
||||
env|sort
|
||||
end_section "Environment"
|
||||
python_cmd "$helpers/codeticket.py" addinput "Viewer Channel" "${viewer_channel}"
|
||||
|
||||
initialize_version # provided by buildscripts build.sh; sets version id
|
||||
|
||||
# Now run the build
|
||||
succeeded=true
|
||||
|
|
@ -214,9 +236,6 @@ build_processes=
|
|||
last_built_variant=
|
||||
for variant in $variants
|
||||
do
|
||||
eval '$build_'"$variant" || continue
|
||||
eval '$build_'"$arch"_"$variant" || continue
|
||||
|
||||
# Only the last built arch is available for upload
|
||||
last_built_variant="$variant"
|
||||
|
||||
|
|
@ -232,6 +251,9 @@ do
|
|||
then
|
||||
begin_section "Build $variant"
|
||||
build "$variant" "$build_dir"
|
||||
end_section "Build $variant"
|
||||
|
||||
begin_section "post-build $variant"
|
||||
if `cat "$build_dir/build_ok"`
|
||||
then
|
||||
case "$variant" in
|
||||
|
|
@ -239,10 +261,11 @@ do
|
|||
if [ -r "$build_dir/autobuild-package.xml" ]
|
||||
then
|
||||
begin_section "Autobuild metadata"
|
||||
upload_item docs "$build_dir/autobuild-package.xml" text/xml
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Autobuild Metadata" "$build_dir/autobuild-package.xml" --mimetype text/xml \
|
||||
|| fatal "Upload of autobuild metadata failed"
|
||||
if [ "$arch" != "Linux" ]
|
||||
then
|
||||
record_dependencies_graph # defined in buildscripts/hg/bin/build.sh
|
||||
record_dependencies_graph "$build_dir/autobuild-package.xml" # defined in buildscripts/hg/bin/build.sh
|
||||
else
|
||||
record_event "TBD - no dependency graph for linux (probable python version dependency)"
|
||||
fi
|
||||
|
|
@ -250,17 +273,25 @@ do
|
|||
else
|
||||
record_event "no autobuild metadata at '$build_dir/autobuild-package.xml'"
|
||||
fi
|
||||
if [ -r "$build_dir/newview/viewer_version.txt" ]
|
||||
then
|
||||
begin_section "Viewer Version"
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Viewer Version" "$(<"$build_dir/newview/viewer_version.txt")" --mimetype inline-text \
|
||||
|| fatal "Upload of viewer version failed"
|
||||
end_section "Viewer Version"
|
||||
fi
|
||||
;;
|
||||
Doxygen)
|
||||
if [ -r "$build_dir/doxygen_warnings.log" ]
|
||||
then
|
||||
record_event "Doxygen warnings generated; see doxygen_warnings.log"
|
||||
upload_item log "$build_dir/doxygen_warnings.log" text/plain
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Log" "$build_dir/doxygen_warnings.log" --mimetype text/plain ## TBD
|
||||
fi
|
||||
if [ -d "$build_dir/doxygen/html" ]
|
||||
then
|
||||
tar -c -f "$build_dir/viewer-doxygen.tar.bz2" --strip-components 3 "$build_dir/doxygen/html"
|
||||
upload_item docs "$build_dir/viewer-doxygen.tar.bz2" binary/octet-stream
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Doxygen Tarball" "$build_dir/viewer-doxygen.tar.bz2" \
|
||||
|| fatal "Upload of doxygen tarball failed"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
|
|
@ -270,7 +301,8 @@ do
|
|||
else
|
||||
record_failure "Build of \"$variant\" failed."
|
||||
fi
|
||||
end_section "Build $variant"
|
||||
end_section "post-build $variant"
|
||||
|
||||
else
|
||||
record_event "configure for $variant failed: build skipped"
|
||||
fi
|
||||
|
|
@ -290,7 +322,7 @@ then
|
|||
if $build_viewer_deb && [ "$last_built_variant" == "Release" ]
|
||||
then
|
||||
begin_section "Build Viewer Debian Package"
|
||||
have_private_repo=false
|
||||
|
||||
# mangle the changelog
|
||||
dch --force-bad-version \
|
||||
--distribution unstable \
|
||||
|
|
@ -320,11 +352,14 @@ then
|
|||
# upload debian package and create repository
|
||||
begin_section "Upload Debian Repository"
|
||||
for deb_file in `/bin/ls ../packages_public/*.deb ../*.deb 2>/dev/null`; do
|
||||
upload_item debian $deb_file binary/octet-stream
|
||||
deb_pkg=$(basename "$deb_file" | sed 's,_.*,,')
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Debian $deb_pkg" $deb_file \
|
||||
|| fatal "Upload of debian $deb_pkg failed"
|
||||
done
|
||||
for deb_file in `/bin/ls ../packages_private/*.deb 2>/dev/null`; do
|
||||
upload_item debian_private $deb_file binary/octet-stream
|
||||
have_private_repo=true
|
||||
deb_pkg=$(basename "$deb_file" | sed 's,_.*,,')
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Debian $deb_pkg" "$deb_file" --private \
|
||||
|| fatal "Upload of debian $deb_pkg failed"
|
||||
done
|
||||
|
||||
create_deb_repo
|
||||
|
|
@ -336,14 +371,6 @@ then
|
|||
mv $build_log_dir/$debian_repo_type $build_log_dir/${debian_repo_type}_pushed
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $have_private_repo = true ]; then
|
||||
eval "$python_command \"$redirect\" '\${private_S3PROXY_URL}${S3PREFIX}repo/$repo/rev/$revision/index.html'"\
|
||||
>"$build_log_dir/private.html" || fatal generating redirect
|
||||
upload_item global_redirect "$build_log_dir/private.html" text/html
|
||||
|
||||
fi
|
||||
|
||||
end_section "Upload Debian Repository"
|
||||
|
||||
else
|
||||
|
|
@ -359,18 +386,17 @@ if $succeeded
|
|||
then
|
||||
if $build_viewer
|
||||
then
|
||||
begin_section Upload Installer
|
||||
begin_section "Uploads"
|
||||
# Upload installer
|
||||
package=$(installer_$arch)
|
||||
if [ x"$package" = x ] || test -d "$package"
|
||||
then
|
||||
record_event "??? mystery event $package // $build_coverity"
|
||||
fatal "No installer found from `pwd`"
|
||||
succeeded=$build_coverity
|
||||
else
|
||||
# Upload base package.
|
||||
upload_item installer "$package" binary/octet-stream
|
||||
upload_item quicklink "$package" binary/octet-stream
|
||||
[ -f $build_dir/summary.json ] && upload_item installer $build_dir/summary.json text/plain
|
||||
python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|
||||
|| fatal "Upload of installer failed"
|
||||
|
||||
# Upload additional packages.
|
||||
for package_id in $additional_packages
|
||||
|
|
@ -378,32 +404,44 @@ then
|
|||
package=$(installer_$arch "$package_id")
|
||||
if [ x"$package" != x ]
|
||||
then
|
||||
upload_item installer "$package" binary/octet-stream
|
||||
upload_item quicklink "$package" binary/octet-stream
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|
||||
|| fatal "Upload of installer $package_id failed"
|
||||
else
|
||||
record_failure "Failed to find additional package for '$package_id'."
|
||||
fi
|
||||
done
|
||||
|
||||
case "$last_built_variant" in
|
||||
Release)
|
||||
# Upload crash reporter files
|
||||
for symbolfile in $symbolfiles
|
||||
do
|
||||
upload_item symbolfile "$build_dir/$symbolfile" binary/octet-stream
|
||||
done
|
||||
if [ "$last_built_variant" = "Release" ]
|
||||
then
|
||||
# nat 2016-12-22: without RELEASE_CRASH_REPORTING, we have no symbol file.
|
||||
if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ]
|
||||
then
|
||||
# Upload crash reporter file
|
||||
# These names must match the set of VIEWER_SYMBOL_FILE in indra/newview/CMakeLists.txt
|
||||
case "$arch" in
|
||||
CYGWIN)
|
||||
symbolfile="$build_dir/newview/Release/secondlife-symbols-windows-${AUTOBUILD_ADDRSIZE}.tar.bz2"
|
||||
;;
|
||||
Darwin)
|
||||
symbolfile="$build_dir/newview/Release/secondlife-symbols-darwin-${AUTOBUILD_ADDRSIZE}.tar.bz2"
|
||||
;;
|
||||
Linux)
|
||||
symbolfile="$build_dir/newview/Release/secondlife-symbols-linux-${AUTOBUILD_ADDRSIZE}.tar.bz2"
|
||||
;;
|
||||
esac
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$symbolfile" \
|
||||
|| fatal "Upload of symbolfile failed"
|
||||
fi
|
||||
|
||||
# Upload the llphysicsextensions_tpv package, if one was produced
|
||||
# *TODO: Make this an upload-extension
|
||||
if [ -r "$build_dir/llphysicsextensions_package" ]
|
||||
then
|
||||
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
|
||||
upload_item private_artifact "$llphysicsextensions_package" binary/octet-stream
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
# Upload the llphysicsextensions_tpv package, if one was produced
|
||||
# *TODO: Make this an upload-extension
|
||||
if [ -r "$build_dir/llphysicsextensions_package" ]
|
||||
then
|
||||
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|
||||
|| fatal "Upload of physics extensions package failed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Run upload extensions
|
||||
if [ -d ${build_dir}/packages/upload-extensions ]; then
|
||||
|
|
@ -414,7 +452,7 @@ then
|
|||
done
|
||||
fi
|
||||
fi
|
||||
end_section Upload Installer
|
||||
end_section "Uploads"
|
||||
else
|
||||
record_event "skipping upload of installer"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ Ansariel Hiller
|
|||
MAINT-7059
|
||||
MAINT-6519
|
||||
MAINT-7899
|
||||
STORM-2105
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# cmake_minimum_required should appear before any
|
||||
# other commands to guarantee full compatibility
|
||||
# with the version specified
|
||||
## prior to 2.8, the add_custom_target commands used in setting the version did not work correctly
|
||||
cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR)
|
||||
## prior to 3.4, the Windows manifest handling was missing
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
|
||||
set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING
|
||||
"The root project/makefile/solution name. Defaults to SecondLife.")
|
||||
|
|
@ -63,7 +63,7 @@ if (LINUX)
|
|||
include(LLAppearanceUtility)
|
||||
add_subdirectory(${LLAPPEARANCEUTILITY_SRC_DIR} ${LLAPPEARANCEUTILITY_BIN_DIR})
|
||||
endif (INSTALL_PROPRIETARY)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target linux-updater)
|
||||
add_dependencies(viewer linux-crash-logger-strip-target)
|
||||
elseif (DARWIN)
|
||||
add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
|
||||
add_dependencies(viewer mac-crash-logger)
|
||||
|
|
@ -75,9 +75,6 @@ elseif (WINDOWS)
|
|||
endif (EXISTS ${VIEWER_DIR}win_setup)
|
||||
# add_dependencies(viewer windows-setup windows-crash-logger)
|
||||
add_dependencies(viewer windows-crash-logger)
|
||||
elseif (SOLARIS)
|
||||
add_subdirectory(solaris_crash_logger)
|
||||
add_dependencies(viewer solaris-crash-logger)
|
||||
endif (LINUX)
|
||||
|
||||
add_subdirectory(${VIEWER_PREFIX}newview)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ Compilation
|
|||
LL_WINDOWS=1 " "
|
||||
UNICODE " "
|
||||
_UNICODE " "
|
||||
WINVER=0x0501 " "
|
||||
_WIN32_WINNT=0x0501 " "
|
||||
WINVER=0x0600 " "
|
||||
_WIN32_WINNT=0x0600 " "
|
||||
LL_OS_DRAGDROP_ENABLED=1 " "
|
||||
LIB_NDOF=1 " "
|
||||
|
||||
|
|
|
|||
|
|
@ -2,18 +2,32 @@
|
|||
#
|
||||
# Compilation options shared by all Second Life components.
|
||||
|
||||
#*****************************************************************************
|
||||
# It's important to realize that CMake implicitly concatenates
|
||||
# CMAKE_CXX_FLAGS with (e.g.) CMAKE_CXX_FLAGS_RELEASE for Release builds. So
|
||||
# set switches in CMAKE_CXX_FLAGS that should affect all builds, but in
|
||||
# CMAKE_CXX_FLAGS_RELEASE or CMAKE_CXX_FLAGS_RELWITHDEBINFO for switches
|
||||
# that should affect only that build variant.
|
||||
#
|
||||
# Also realize that CMAKE_CXX_FLAGS may already be partially populated on
|
||||
# entry to this file.
|
||||
#*****************************************************************************
|
||||
|
||||
if(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
|
||||
set(${CMAKE_CURRENT_LIST_FILE}_INCLUDED "YES")
|
||||
|
||||
include(Variables)
|
||||
|
||||
# Portable compilation flags.
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE
|
||||
"-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -DNDEBUG")
|
||||
# We go to some trouble to set LL_BUILD to the set of relevant compiler flags.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}")
|
||||
# Given that, all the flags you see added below are flags NOT present in
|
||||
# https://bitbucket.org/lindenlab/viewer-build-variables/src/tip/variables.
|
||||
# Before adding new ones here, it's important to ask: can this flag really be
|
||||
# applied to the viewer only, or should/must it be applied to all 3p libraries
|
||||
# as well?
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
"-DLL_RELEASE=1 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1")
|
||||
# Portable compilation flags.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DADDRESS_SIZE=${ADDRESS_SIZE}")
|
||||
|
||||
# Configure crash reporting
|
||||
set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
|
||||
|
|
@ -46,26 +60,25 @@ if (WINDOWS)
|
|||
# http://www.cmake.org/pipermail/cmake/2009-September/032143.html
|
||||
string(REPLACE "/Zm1000" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP -D_SCL_SECURE_NO_WARNINGS=1"
|
||||
CACHE STRING "C++ compiler debug options" FORCE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /Zo /MD /MP /Ob0 -D_SECURE_STL=0"
|
||||
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
|
||||
CACHE STRING "C++ compiler release-with-debug options" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /Zo /MD /MP /Ob2 -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0"
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /Zo"
|
||||
CACHE STRING "C++ compiler release options" FORCE)
|
||||
# zlib has assembly-language object files incompatible with SAFESEH
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE /SAFESEH:NO /NODEFAULTLIB:LIBCMT")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE /SAFESEH:NO /NODEFAULTLIB:LIBCMT /IGNORE:4099")
|
||||
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "")
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "")
|
||||
|
||||
add_definitions(
|
||||
/DLL_WINDOWS=1
|
||||
/DNOMINMAX
|
||||
# /DDOM_DYNAMIC # For shared library colladadom
|
||||
/DUNICODE
|
||||
/D_UNICODE
|
||||
)
|
||||
add_compile_options(
|
||||
/GS
|
||||
/TP
|
||||
/W3
|
||||
|
|
@ -73,94 +86,41 @@ if (WINDOWS)
|
|||
/Zc:forScope
|
||||
/nologo
|
||||
/Oy-
|
||||
/Zc:wchar_t-
|
||||
/arch:SSE2
|
||||
# /arch:SSE2
|
||||
/fp:fast
|
||||
)
|
||||
|
||||
# Nicky: x64 implies SSE2
|
||||
if( ADDRESS_SIZE EQUAL 32 )
|
||||
add_definitions( /arch:SSE2 )
|
||||
endif()
|
||||
|
||||
# Are we using the crummy Visual Studio KDU build workaround?
|
||||
if (NOT VS_DISABLE_FATAL_WARNINGS)
|
||||
add_definitions(/WX)
|
||||
endif (NOT VS_DISABLE_FATAL_WARNINGS)
|
||||
|
||||
# configure Win32 API for Windows Vista+ compatibility
|
||||
set(WINVER "0x0600" CACHE STRING "Win32 API Target version (see http://msdn.microsoft.com/en-us/library/aa383745%28v=VS.85%29.aspx)")
|
||||
add_definitions("/DWINVER=${WINVER}" "/D_WIN32_WINNT=${WINVER}")
|
||||
endif (WINDOWS)
|
||||
|
||||
|
||||
if (LINUX)
|
||||
set(CMAKE_SKIP_RPATH TRUE)
|
||||
|
||||
# Here's a giant hack for Fedora 8, where we can't use
|
||||
# _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1.
|
||||
add_definitions(-D_FORTIFY_SOURCE=2)
|
||||
|
||||
find_program(GXX g++)
|
||||
mark_as_advanced(GXX)
|
||||
|
||||
if (GXX)
|
||||
execute_process(
|
||||
COMMAND ${GXX} --version
|
||||
COMMAND sed "s/^[gc+ ]*//"
|
||||
COMMAND head -1
|
||||
OUTPUT_VARIABLE GXX_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (GXX)
|
||||
set(GXX_VERSION x)
|
||||
endif (GXX)
|
||||
|
||||
# The quoting hack here is necessary in case we're using distcc or
|
||||
# ccache as our compiler. CMake doesn't pass the command line
|
||||
# through the shell by default, so we end up trying to run "distcc"
|
||||
# " g++" - notice the leading space. Ugh.
|
||||
|
||||
execute_process(
|
||||
COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} --version"
|
||||
COMMAND sed "s/^[gc+ ]*//"
|
||||
COMMAND head -1
|
||||
OUTPUT_VARIABLE CXX_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if (${GXX_VERSION} STREQUAL ${CXX_VERSION})
|
||||
add_definitions(-D_FORTIFY_SOURCE=2)
|
||||
else (${GXX_VERSION} STREQUAL ${CXX_VERSION})
|
||||
if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat")
|
||||
add_definitions(-D_FORTIFY_SOURCE=2)
|
||||
endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat")
|
||||
endif (${GXX_VERSION} STREQUAL ${CXX_VERSION})
|
||||
|
||||
# Let's actually get a numerical version of gxx's version
|
||||
STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION})
|
||||
|
||||
# Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables
|
||||
# This is pure rubbish; I wish there was another way.
|
||||
#
|
||||
if(${CXX_VERSION_NUMBER} LESS 420)
|
||||
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}")
|
||||
endif (${CXX_VERSION_NUMBER} LESS 420)
|
||||
|
||||
if(${CXX_VERSION_NUMBER} GREATER 459)
|
||||
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}")
|
||||
endif (${CXX_VERSION_NUMBER} GREATER 459)
|
||||
set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
# gcc 4.3 and above don't like the LL boost and also
|
||||
# cause warnings due to our use of deprecated headers
|
||||
if(${CXX_VERSION_NUMBER} GREATER 429)
|
||||
add_definitions(-Wno-parentheses)
|
||||
set(CMAKE_CXX_FLAGS "-Wno-deprecated ${CMAKE_CXX_FLAGS}")
|
||||
endif (${CXX_VERSION_NUMBER} GREATER 429)
|
||||
|
||||
# End of hacks.
|
||||
add_definitions(-Wno-parentheses)
|
||||
|
||||
add_definitions(
|
||||
-DLL_LINUX=1
|
||||
-D_REENTRANT
|
||||
)
|
||||
add_compile_options(
|
||||
-fexceptions
|
||||
-fno-math-errno
|
||||
-fno-strict-aliasing
|
||||
-fsigned-char
|
||||
-g
|
||||
-msse2
|
||||
-mfpmath=sse
|
||||
-pthread
|
||||
|
|
@ -170,39 +130,47 @@ if (LINUX)
|
|||
add_definitions(-DEXTERNAL_TOS)
|
||||
|
||||
add_definitions(-DAPPID=secondlife)
|
||||
add_definitions(-fvisibility=hidden)
|
||||
# don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway.
|
||||
add_compile_options(-fvisibility=hidden)
|
||||
# don't catch SIGCHLD in our base application class for the viewer - some of
|
||||
# our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The
|
||||
# viewer doesn't need to catch SIGCHLD anyway.
|
||||
add_definitions(-DLL_IGNORE_SIGCHLD)
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
add_definitions(-march=pentium4)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
add_definitions(-mfpmath=sse)
|
||||
#add_definitions(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
|
||||
if (ADDRESS_SIZE EQUAL 32)
|
||||
add_compile_options(-march=pentium4)
|
||||
endif (ADDRESS_SIZE EQUAL 32)
|
||||
#add_compile_options(-ftree-vectorize) # THIS CRASHES GCC 3.1-3.2
|
||||
if (NOT USESYSTEMLIBS)
|
||||
# this stops us requiring a really recent glibc at runtime
|
||||
add_definitions(-fno-stack-protector)
|
||||
add_compile_options(-fno-stack-protector)
|
||||
# linking can be very memory-hungry, especially the final viewer link
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory")
|
||||
endif (NOT USESYSTEMLIBS)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
endif (LINUX)
|
||||
|
||||
|
||||
if (DARWIN)
|
||||
add_definitions(-DLL_DARWIN=1)
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-no_compact_unwind -Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
|
||||
set(DARWIN_extra_cstar_flags "-g -Wno-unused-local-typedef -Wno-deprecated-declarations")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}")
|
||||
set(DARWIN_extra_cstar_flags "-Wno-unused-local-typedef -Wno-deprecated-declarations")
|
||||
# Ensure that CMAKE_CXX_FLAGS has the correct -g debug information format --
|
||||
# see Variables.cmake.
|
||||
string(REPLACE "-gdwarf-2" "-g${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}"
|
||||
CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
# The viewer code base can now be successfully compiled with -std=c++14. But
|
||||
# turning that on in the generic viewer-build-variables/variables file would
|
||||
# potentially require tweaking each of our ~50 third-party library builds.
|
||||
# Until we decide to set -std=c++14 in viewer-build-variables/variables, set
|
||||
# it locally here: we want to at least prevent inadvertently reintroducing
|
||||
# viewer code that would fail with C++14.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags} -std=c++14")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}")
|
||||
# NOTE: it's critical that the optimization flag is put in front.
|
||||
# NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
set(ENABLE_SIGNING TRUE)
|
||||
set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
|
||||
## Really?? On developer machines too?
|
||||
##set(ENABLE_SIGNING TRUE)
|
||||
##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
|
||||
endif (DARWIN)
|
||||
|
||||
|
||||
|
|
@ -226,22 +194,17 @@ if (LINUX OR DARWIN)
|
|||
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
|
||||
elseif (WORD_SIZE EQUAL 64)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64")
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m${ADDRESS_SIZE}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m${ADDRESS_SIZE}")
|
||||
endif (LINUX OR DARWIN)
|
||||
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
add_definitions(-DLL_USESYSTEMLIBS=1)
|
||||
|
||||
if (LINUX AND ${ARCH} STREQUAL "i686")
|
||||
if (LINUX AND ADDRESS_SIZE EQUAL 32)
|
||||
add_definitions(-march=pentiumpro)
|
||||
endif (LINUX AND ${ARCH} STREQUAL "i686")
|
||||
endif (LINUX AND ADDRESS_SIZE EQUAL 32)
|
||||
|
||||
else (USESYSTEMLIBS)
|
||||
set(${ARCH}_linux_INCLUDES
|
||||
|
|
|
|||
|
|
@ -2,9 +2,18 @@
|
|||
# Construct the version and copyright information based on package data.
|
||||
include(Python)
|
||||
|
||||
# packages-formatter.py runs autobuild install --versions, which needs to know
|
||||
# the build_directory, which (on Windows) depends on AUTOBUILD_ADDRSIZE.
|
||||
# Within an autobuild build, AUTOBUILD_ADDRSIZE is already set. But when
|
||||
# building in an IDE, it probably isn't. Set it explicitly using
|
||||
# run_build_test.py.
|
||||
add_custom_command(OUTPUT packages-info.txt
|
||||
COMMENT Generating packages-info.txt for the about box
|
||||
MAIN_DEPENDENCY ${CMAKE_SOURCE_DIR}/../autobuild.xml
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py > packages-info.txt
|
||||
${CMAKE_SOURCE_DIR}/../autobuild.xml
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/cmake/run_build_test.py -DAUTOBUILD_ADDRSIZE=${ADDRESS_SIZE}
|
||||
${PYTHON_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/../scripts/packages-formatter.py "${VIEWER_CHANNEL}" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}" > packages-info.txt
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
|
|||
set(VIEWER_VERSION_REVISION $ENV{revision})
|
||||
message(STATUS "Revision (from environment): ${VIEWER_VERSION_REVISION}")
|
||||
|
||||
elseif (DEFINED ENV{AUTOBUILD_BUILD_ID})
|
||||
set(VIEWER_VERSION_REVISION $ENV{AUTOBUILD_BUILD_ID})
|
||||
message(STATUS "Revision (from autobuild environment): ${VIEWER_VERSION_REVISION}")
|
||||
|
||||
else (DEFINED ENV{revision})
|
||||
find_program(MERCURIAL
|
||||
NAMES hg
|
||||
|
|
@ -54,7 +58,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n
|
|||
endif ("${VIEWER_VERSION_REVISION}" STREQUAL "")
|
||||
|
||||
set(VIEWER_CHANNEL_VERSION_DEFINES
|
||||
"LL_VIEWER_CHANNEL=\"${VIEWER_CHANNEL}\""
|
||||
"LL_VIEWER_CHANNEL=${VIEWER_CHANNEL}"
|
||||
"LL_VIEWER_VERSION_MAJOR=${VIEWER_VERSION_MAJOR}"
|
||||
"LL_VIEWER_VERSION_MINOR=${VIEWER_VERSION_MINOR}"
|
||||
"LL_VIEWER_VERSION_PATCH=${VIEWER_VERSION_PATCH}"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ if (USESYSTEMLIBS)
|
|||
set(CEFPLUGIN OFF CACHE BOOL
|
||||
"CEFPLUGIN support for the llplugin/llmedia test apps.")
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(llceflib)
|
||||
use_prebuilt_binary(dullahan)
|
||||
set(CEFPLUGIN ON CACHE BOOL
|
||||
"CEFPLUGIN support for the llplugin/llmedia test apps.")
|
||||
set(CEF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/cef)
|
||||
|
|
@ -16,7 +16,7 @@ if (WINDOWS)
|
|||
set(CEF_PLUGIN_LIBRARIES
|
||||
libcef.lib
|
||||
libcef_dll_wrapper.lib
|
||||
llceflib.lib
|
||||
dullahan.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
FIND_LIBRARY(APPKIT_LIBRARY AppKit)
|
||||
|
|
@ -31,7 +31,7 @@ elseif (DARWIN)
|
|||
|
||||
set(CEF_PLUGIN_LIBRARIES
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libLLCefLib.a
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a
|
||||
${APPKIT_LIBRARY}
|
||||
${CEF_LIBRARY}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ set(cmake_SOURCE_FILES
|
|||
FindFMODEX.cmake
|
||||
FindGLH.cmake
|
||||
FindGoogleBreakpad.cmake
|
||||
FindGooglePerfTools.cmake
|
||||
FindHUNSPELL.cmake
|
||||
FindJsonCpp.cmake
|
||||
FindNDOF.cmake
|
||||
|
|
@ -45,12 +44,8 @@ set(cmake_SOURCE_FILES
|
|||
GLH.cmake
|
||||
GLOD.cmake
|
||||
## GStreamer010Plugin.cmake
|
||||
GetPrerequisites_2_8.cmake
|
||||
## Glui.cmake
|
||||
Glut.cmake
|
||||
GoogleBreakpad.cmake
|
||||
GoogleMock.cmake
|
||||
GooglePerfTools.cmake
|
||||
Havok.cmake
|
||||
Hunspell.cmake
|
||||
JPEG.cmake
|
||||
|
|
@ -90,7 +85,6 @@ set(cmake_SOURCE_FILES
|
|||
Prebuilt.cmake
|
||||
PulseAudio.cmake
|
||||
Python.cmake
|
||||
QuickTimePlugin.cmake
|
||||
TemplateCheck.cmake
|
||||
Tut.cmake
|
||||
UI.cmake
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ SET(DEBUG_PKG_CONFIG "YES")
|
|||
IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "")
|
||||
|
||||
# Guess at architecture-specific system library paths.
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
if (ADDRESS_SIZE EQUAL 32)
|
||||
SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib)
|
||||
SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib)
|
||||
SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu)
|
||||
SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu)
|
||||
else (WORD_SIZE EQUAL 32)
|
||||
else (ADDRESS_SIZE EQUAL 32)
|
||||
SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib)
|
||||
SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib)
|
||||
SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu)
|
||||
SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
endif (ADDRESS_SIZE EQUAL 32)
|
||||
|
||||
# Use DPKG architecture, if available.
|
||||
IF (${DPKG_ARCH})
|
||||
|
|
|
|||
|
|
@ -27,18 +27,6 @@ if(WINDOWS)
|
|||
#*******************************
|
||||
# Misc shared libs
|
||||
|
||||
set(debug_src_dir "${ARCH_PREBUILT_DIRS_DEBUG}")
|
||||
set(debug_files
|
||||
openjpegd.dll
|
||||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
ssleay32.dll
|
||||
libeay32.dll
|
||||
glod.dll
|
||||
libhunspell.dll
|
||||
)
|
||||
|
||||
set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")
|
||||
set(release_files
|
||||
openjpeg.dll
|
||||
|
|
@ -47,18 +35,18 @@ if(WINDOWS)
|
|||
libapriconv-1.dll
|
||||
ssleay32.dll
|
||||
libeay32.dll
|
||||
nghttp2.dll
|
||||
glod.dll
|
||||
libhunspell.dll
|
||||
)
|
||||
|
||||
if(USE_TCMALLOC)
|
||||
set(debug_files ${debug_files} libtcmalloc_minimal-debug.dll)
|
||||
set(release_files ${release_files} libtcmalloc_minimal.dll)
|
||||
endif(USE_TCMALLOC)
|
||||
|
||||
if (FMODEX)
|
||||
set(debug_files ${debug_files} fmodexL.dll)
|
||||
set(release_files ${release_files} fmodex.dll)
|
||||
|
||||
if(ADDRESS_SIZE EQUAL 32)
|
||||
set(release_files ${release_files} fmodex.dll)
|
||||
else(ADDRESS_SIZE EQUAL 32)
|
||||
set(release_files ${release_files} fmodex64.dll)
|
||||
endif(ADDRESS_SIZE EQUAL 32)
|
||||
endif (FMODEX)
|
||||
|
||||
#*******************************
|
||||
|
|
@ -77,8 +65,9 @@ if(WINDOWS)
|
|||
endif (MSVC80)
|
||||
|
||||
# try to copy VS2010 redist independently of system version
|
||||
list(APPEND LMSVC_VER 100)
|
||||
list(APPEND LMSVC_VERDOT 10.0)
|
||||
# maint-7360 CP
|
||||
# list(APPEND LMSVC_VER 100)
|
||||
# list(APPEND LMSVC_VERDOT 10.0)
|
||||
|
||||
list(LENGTH LMSVC_VER count)
|
||||
math(EXPR count "${count}-1")
|
||||
|
|
@ -112,12 +101,17 @@ if(WINDOWS)
|
|||
unset(debug_msvc_redist_path CACHE)
|
||||
endif()
|
||||
|
||||
if(ADDRESS_SIZE EQUAL 32)
|
||||
# this folder contains the 32bit DLLs.. (yes really!)
|
||||
set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64")
|
||||
else(ADDRESS_SIZE EQUAL 32)
|
||||
# this folder contains the 64bit DLLs.. (yes really!)
|
||||
set(registry_find_path "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32")
|
||||
endif(ADDRESS_SIZE EQUAL 32)
|
||||
|
||||
FIND_PATH(release_msvc_redist_path NAME msvcr${MSVC_VER}.dll
|
||||
PATHS
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\${MSVC_VERDOT}\\Setup\\VC;ProductDir]/redist/x86/Microsoft.VC${MSVC_VER}.CRT
|
||||
[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/SysWOW64
|
||||
[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Windows;Directory]/System32
|
||||
${MSVC_REDIST_PATH}
|
||||
${registry_find_path}
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
|
|
@ -169,11 +163,12 @@ elseif(DARWIN)
|
|||
libaprutil-1.0.dylib
|
||||
libaprutil-1.dylib
|
||||
libexception_handler.dylib
|
||||
libexpat.1.5.2.dylib
|
||||
libexpat.dylib
|
||||
${EXPAT_COPY}
|
||||
libGLOD.dylib
|
||||
libhunspell-1.3.0.dylib
|
||||
libndofdev.dylib
|
||||
libnghttp2.dylib
|
||||
libnghttp2.14.dylib
|
||||
libnghttp2.14.14.0.dylib
|
||||
)
|
||||
|
||||
if (FMODEX)
|
||||
|
|
@ -211,8 +206,7 @@ elseif(LINUX)
|
|||
libaprutil-1.so.0
|
||||
libatk-1.0.so
|
||||
libdb-5.1.so
|
||||
libexpat.so
|
||||
libexpat.so.1
|
||||
${EXPAT_COPY}
|
||||
libfreetype.so.6.6.2
|
||||
libfreetype.so.6
|
||||
libGLOD.so
|
||||
|
|
@ -227,10 +221,6 @@ elseif(LINUX)
|
|||
libfontconfig.so.1
|
||||
)
|
||||
|
||||
if (USE_TCMALLOC)
|
||||
set(release_files ${release_files} "libtcmalloc_minimal.so")
|
||||
endif (USE_TCMALLOC)
|
||||
|
||||
if (FMODEX)
|
||||
set(debug_files ${debug_files} "libfmodexL.so")
|
||||
set(release_files ${release_files} "libfmodex.so")
|
||||
|
|
@ -287,13 +277,13 @@ set(third_party_targets ${third_party_targets} ${out_targets})
|
|||
|
||||
|
||||
|
||||
copy_if_different(
|
||||
${debug_src_dir}
|
||||
"${SHARED_LIB_STAGING_DIR_DEBUG}"
|
||||
out_targets
|
||||
${debug_files}
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} ${out_targets})
|
||||
#copy_if_different(
|
||||
# ${debug_src_dir}
|
||||
# "${SHARED_LIB_STAGING_DIR_DEBUG}"
|
||||
# out_targets
|
||||
# ${debug_files}
|
||||
# )
|
||||
#set(third_party_targets ${third_party_targets} ${out_targets})
|
||||
|
||||
copy_if_different(
|
||||
${release_src_dir}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,9 @@
|
|||
# SEARCH_DIRS= The full paths to dirs to search for dependencies.
|
||||
# DST_PATH= The full path where the dependecies will be copied.
|
||||
|
||||
# *FIX:Mani - I pulled in the CMake 2.8 GetPrerequisites.cmake script here, because it works on windows where 2.6 did not.
|
||||
# Once we have officially upgraded to 2.8 we can just use that version of GetPrerequisites.cmake.
|
||||
get_filename_component(current_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
include(${current_dir}/GetPrerequisites_2_8.cmake)
|
||||
include(GetPrerequisites)
|
||||
|
||||
message("Getting recursive dependencies for file: ${BIN_NAME}")
|
||||
message(STATUS "Getting recursive dependencies for file: ${BIN_NAME}")
|
||||
|
||||
set(EXCLUDE_SYSTEM 1)
|
||||
set(RECURSE 1)
|
||||
|
|
@ -21,7 +18,7 @@ get_filename_component(EXE_PATH ${BIN_NAME} PATH)
|
|||
get_prerequisites( ${BIN_NAME} RESULTS ${EXCLUDE_SYSTEM} ${RECURSE} "${EXE_PATH}" "${SEARCH_DIRS}" )
|
||||
|
||||
foreach(DEP ${RESULTS})
|
||||
Message("Processing dependency: ${DEP}")
|
||||
Message(STATUS "Processing dependency: ${DEP}")
|
||||
get_filename_component(DEP_FILE ${DEP} NAME)
|
||||
set(DEP_FILES ${DEP_FILES} ${DEP_FILE})
|
||||
endforeach(DEP)
|
||||
|
|
@ -64,10 +61,10 @@ if(FOUND_FILES)
|
|||
foreach(FILE ${FOUND_FILES})
|
||||
get_filename_component(DST_FILE ${FILE} NAME)
|
||||
set(DST_FILE "${DST_PATH}/${DST_FILE}")
|
||||
message("Copying ${FILE} to ${DST_FILE}")
|
||||
message(STATUS "Copying ${FILE} to ${DST_FILE}")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FILE} ${DST_FILE}
|
||||
)
|
||||
endforeach(FILE ${FOUND_FILES})
|
||||
endif(FOUND_FILES)
|
||||
message("Success!")
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,14 @@ else (USESYSTEMLIBS)
|
|||
use_prebuilt_binary(expat)
|
||||
if (WINDOWS)
|
||||
set(EXPAT_LIBRARIES libexpatMT)
|
||||
set(EXPAT_COPY libexpatMT.dll)
|
||||
else (WINDOWS)
|
||||
set(EXPAT_LIBRARIES expat)
|
||||
if (DARWIN)
|
||||
set(EXPAT_COPY libexpat.1.dylib libexpat.dylib)
|
||||
else ()
|
||||
set(EXPAT_COPY libexpat.so.1 libexpat.so)
|
||||
endif ()
|
||||
endif (WINDOWS)
|
||||
set(EXPAT_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ find_path(HUNSPELL_INCLUDE_DIR hunspell.h
|
|||
PATH_SUFFIXES hunspell
|
||||
)
|
||||
|
||||
set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3.0 libhunspell)
|
||||
set(HUNSPELL_NAMES ${HUNSPELL_NAMES} libhunspell-1.3 libhunspell)
|
||||
find_library(HUNSPELL_LIBRARY
|
||||
NAMES ${HUNSPELL_NAMES}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ if (NOT USESYSTEMLIBS)
|
|||
if (WINDOWS OR LINUX)
|
||||
use_prebuilt_binary(glext)
|
||||
endif (WINDOWS OR LINUX)
|
||||
use_prebuilt_binary(glh-linear)
|
||||
use_prebuilt_binary(glh_linear)
|
||||
set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
|
||||
endif (NOT USESYSTEMLIBS)
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ set(GLH_FIND_QUIETLY TRUE)
|
|||
if (USESYSTEMLIBS)
|
||||
include(FindGLH)
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(glh-linear)
|
||||
use_prebuilt_binary(glh_linear)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
|
|
|||
|
|
@ -1,786 +0,0 @@
|
|||
# GetPrerequisites.cmake
|
||||
#
|
||||
# This script provides functions to list the .dll, .dylib or .so files that an
|
||||
# executable or shared library file depends on. (Its prerequisites.)
|
||||
#
|
||||
# It uses various tools to obtain the list of required shared library files:
|
||||
# dumpbin (Windows)
|
||||
# ldd (Linux/Unix)
|
||||
# otool (Mac OSX)
|
||||
#
|
||||
# The following functions are provided by this script:
|
||||
# gp_append_unique
|
||||
# is_file_executable
|
||||
# gp_item_default_embedded_path
|
||||
# (projects can override with gp_item_default_embedded_path_override)
|
||||
# gp_resolve_item
|
||||
# (projects can override with gp_resolve_item_override)
|
||||
# gp_resolved_file_type
|
||||
# gp_file_type
|
||||
# get_prerequisites
|
||||
# list_prerequisites
|
||||
# list_prerequisites_by_glob
|
||||
#
|
||||
# Requires CMake 2.6 or greater because it uses function, break, return and
|
||||
# PARENT_SCOPE.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2008-2009 Kitware, Inc.
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distributed this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
|
||||
# gp_append_unique list_var value
|
||||
#
|
||||
# Append value to the list variable ${list_var} only if the value is not
|
||||
# already in the list.
|
||||
#
|
||||
function(gp_append_unique list_var value)
|
||||
set(contains 0)
|
||||
|
||||
foreach(item ${${list_var}})
|
||||
if("${item}" STREQUAL "${value}")
|
||||
set(contains 1)
|
||||
break()
|
||||
endif("${item}" STREQUAL "${value}")
|
||||
endforeach(item)
|
||||
|
||||
if(NOT contains)
|
||||
set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
|
||||
endif(NOT contains)
|
||||
endfunction(gp_append_unique)
|
||||
|
||||
|
||||
# is_file_executable file result_var
|
||||
#
|
||||
# Return 1 in ${result_var} if ${file} is a binary executable.
|
||||
#
|
||||
# Return 0 in ${result_var} otherwise.
|
||||
#
|
||||
function(is_file_executable file result_var)
|
||||
#
|
||||
# A file is not executable until proven otherwise:
|
||||
#
|
||||
set(${result_var} 0 PARENT_SCOPE)
|
||||
|
||||
get_filename_component(file_full "${file}" ABSOLUTE)
|
||||
string(TOLOWER "${file_full}" file_full_lower)
|
||||
|
||||
# If file name ends in .exe on Windows, *assume* executable:
|
||||
#
|
||||
if(WIN32)
|
||||
if("${file_full_lower}" MATCHES "\\.exe$")
|
||||
set(${result_var} 1 PARENT_SCOPE)
|
||||
return()
|
||||
endif("${file_full_lower}" MATCHES "\\.exe$")
|
||||
|
||||
# A clause could be added here that uses output or return value of dumpbin
|
||||
# to determine ${result_var}. In 99%+? practical cases, the exe name
|
||||
# match will be sufficient...
|
||||
#
|
||||
endif(WIN32)
|
||||
|
||||
# Use the information returned from the Unix shell command "file" to
|
||||
# determine if ${file_full} should be considered an executable file...
|
||||
#
|
||||
# If the file command's output contains "executable" and does *not* contain
|
||||
# "text" then it is likely an executable suitable for prerequisite analysis
|
||||
# via the get_prerequisites macro.
|
||||
#
|
||||
if(UNIX)
|
||||
if(NOT file_cmd)
|
||||
find_program(file_cmd "file")
|
||||
endif(NOT file_cmd)
|
||||
|
||||
if(file_cmd)
|
||||
execute_process(COMMAND "${file_cmd}" "${file_full}"
|
||||
OUTPUT_VARIABLE file_ov
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Replace the name of the file in the output with a placeholder token
|
||||
# (the string " _file_full_ ") so that just in case the path name of
|
||||
# the file contains the word "text" or "executable" we are not fooled
|
||||
# into thinking "the wrong thing" because the file name matches the
|
||||
# other 'file' command output we are looking for...
|
||||
#
|
||||
string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
|
||||
string(TOLOWER "${file_ov}" file_ov)
|
||||
|
||||
#message(STATUS "file_ov='${file_ov}'")
|
||||
if("${file_ov}" MATCHES "executable")
|
||||
#message(STATUS "executable!")
|
||||
if("${file_ov}" MATCHES "text")
|
||||
#message(STATUS "but text, so *not* a binary executable!")
|
||||
else("${file_ov}" MATCHES "text")
|
||||
set(${result_var} 1 PARENT_SCOPE)
|
||||
return()
|
||||
endif("${file_ov}" MATCHES "text")
|
||||
endif("${file_ov}" MATCHES "executable")
|
||||
else(file_cmd)
|
||||
message(STATUS "warning: No 'file' command, skipping execute_process...")
|
||||
endif(file_cmd)
|
||||
endif(UNIX)
|
||||
endfunction(is_file_executable)
|
||||
|
||||
|
||||
# gp_item_default_embedded_path item default_embedded_path_var
|
||||
#
|
||||
# Return the path that others should refer to the item by when the item
|
||||
# is embedded inside a bundle.
|
||||
#
|
||||
# Override on a per-project basis by providing a project-specific
|
||||
# gp_item_default_embedded_path_override function.
|
||||
#
|
||||
function(gp_item_default_embedded_path item default_embedded_path_var)
|
||||
|
||||
# On Windows and Linux, "embed" prerequisites in the same directory
|
||||
# as the executable by default:
|
||||
#
|
||||
set(path "@executable_path")
|
||||
set(overridden 0)
|
||||
|
||||
# On the Mac, relative to the executable depending on the type
|
||||
# of the thing we are embedding:
|
||||
#
|
||||
if(APPLE)
|
||||
#
|
||||
# The assumption here is that all executables in the bundle will be
|
||||
# in same-level-directories inside the bundle. The parent directory
|
||||
# of an executable inside the bundle should be MacOS or a sibling of
|
||||
# MacOS and all embedded paths returned from here will begin with
|
||||
# "@executable_path/../" and will work from all executables in all
|
||||
# such same-level-directories inside the bundle.
|
||||
#
|
||||
|
||||
# By default, embed things right next to the main bundle executable:
|
||||
#
|
||||
set(path "@executable_path/../../Contents/MacOS")
|
||||
|
||||
# Embed .dylibs right next to the main bundle executable:
|
||||
#
|
||||
if(item MATCHES "\\.dylib$")
|
||||
set(path "@executable_path/../MacOS")
|
||||
set(overridden 1)
|
||||
endif(item MATCHES "\\.dylib$")
|
||||
|
||||
# Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
|
||||
#
|
||||
if(NOT overridden)
|
||||
if(item MATCHES "[^/]+\\.framework/")
|
||||
set(path "@executable_path/../Frameworks")
|
||||
set(overridden 1)
|
||||
endif(item MATCHES "[^/]+\\.framework/")
|
||||
endif(NOT overridden)
|
||||
endif()
|
||||
|
||||
# Provide a hook so that projects can override the default embedded location
|
||||
# of any given library by whatever logic they choose:
|
||||
#
|
||||
if(COMMAND gp_item_default_embedded_path_override)
|
||||
gp_item_default_embedded_path_override("${item}" path)
|
||||
endif(COMMAND gp_item_default_embedded_path_override)
|
||||
|
||||
set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
|
||||
endfunction(gp_item_default_embedded_path)
|
||||
|
||||
|
||||
# gp_resolve_item context item exepath dirs resolved_item_var
|
||||
#
|
||||
# Resolve an item into an existing full path file.
|
||||
#
|
||||
# Override on a per-project basis by providing a project-specific
|
||||
# gp_resolve_item_override function.
|
||||
#
|
||||
function(gp_resolve_item context item exepath dirs resolved_item_var)
|
||||
set(resolved 0)
|
||||
set(resolved_item "${item}")
|
||||
|
||||
# Is it already resolved?
|
||||
#
|
||||
if(EXISTS "${resolved_item}")
|
||||
set(resolved 1)
|
||||
endif(EXISTS "${resolved_item}")
|
||||
|
||||
if(NOT resolved)
|
||||
if(item MATCHES "@executable_path")
|
||||
#
|
||||
# @executable_path references are assumed relative to exepath
|
||||
#
|
||||
string(REPLACE "@executable_path" "${exepath}" ri "${item}")
|
||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
||||
|
||||
if(EXISTS "${ri}")
|
||||
#message(STATUS "info: embedded item exists (${ri})")
|
||||
set(resolved 1)
|
||||
set(resolved_item "${ri}")
|
||||
else(EXISTS "${ri}")
|
||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
||||
endif(EXISTS "${ri}")
|
||||
endif(item MATCHES "@executable_path")
|
||||
endif(NOT resolved)
|
||||
|
||||
if(NOT resolved)
|
||||
if(item MATCHES "@loader_path")
|
||||
#
|
||||
# @loader_path references are assumed relative to the
|
||||
# PATH of the given "context" (presumably another library)
|
||||
#
|
||||
get_filename_component(contextpath "${context}" PATH)
|
||||
string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
|
||||
get_filename_component(ri "${ri}" ABSOLUTE)
|
||||
|
||||
if(EXISTS "${ri}")
|
||||
#message(STATUS "info: embedded item exists (${ri})")
|
||||
set(resolved 1)
|
||||
set(resolved_item "${ri}")
|
||||
else(EXISTS "${ri}")
|
||||
message(STATUS "warning: embedded item does not exist '${ri}'")
|
||||
endif(EXISTS "${ri}")
|
||||
endif(item MATCHES "@loader_path")
|
||||
endif(NOT resolved)
|
||||
|
||||
if(NOT resolved)
|
||||
set(ri "ri-NOTFOUND")
|
||||
find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
|
||||
find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
|
||||
if(ri)
|
||||
#message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
|
||||
set(resolved 1)
|
||||
set(resolved_item "${ri}")
|
||||
set(ri "ri-NOTFOUND")
|
||||
endif(ri)
|
||||
endif(NOT resolved)
|
||||
|
||||
if(NOT resolved)
|
||||
if(item MATCHES "[^/]+\\.framework/")
|
||||
set(fw "fw-NOTFOUND")
|
||||
find_file(fw "${item}"
|
||||
"~/Library/Frameworks"
|
||||
"/Library/Frameworks"
|
||||
"/System/Library/Frameworks"
|
||||
)
|
||||
if(fw)
|
||||
#message(STATUS "info: 'find_file' found framework (${fw})")
|
||||
set(resolved 1)
|
||||
set(resolved_item "${fw}")
|
||||
set(fw "fw-NOTFOUND")
|
||||
endif(fw)
|
||||
endif(item MATCHES "[^/]+\\.framework/")
|
||||
endif(NOT resolved)
|
||||
|
||||
# Using find_program on Windows will find dll files that are in the PATH.
|
||||
# (Converting simple file names into full path names if found.)
|
||||
#
|
||||
if(WIN32)
|
||||
if(NOT resolved)
|
||||
set(ri "ri-NOTFOUND")
|
||||
find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
|
||||
find_program(ri "${item}" PATHS "${exepath};${dirs}")
|
||||
if(ri)
|
||||
#message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
|
||||
set(resolved 1)
|
||||
set(resolved_item "${ri}")
|
||||
set(ri "ri-NOTFOUND")
|
||||
endif(ri)
|
||||
endif(NOT resolved)
|
||||
endif(WIN32)
|
||||
|
||||
# Provide a hook so that projects can override item resolution
|
||||
# by whatever logic they choose:
|
||||
#
|
||||
if(COMMAND gp_resolve_item_override)
|
||||
gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
|
||||
endif(COMMAND gp_resolve_item_override)
|
||||
|
||||
if(NOT resolved)
|
||||
message(STATUS "
|
||||
warning: cannot resolve item '${item}'
|
||||
|
||||
possible problems:
|
||||
need more directories?
|
||||
need to use InstallRequiredSystemLibraries?
|
||||
run in install tree instead of build tree?
|
||||
")
|
||||
# message(STATUS "
|
||||
#******************************************************************************
|
||||
#warning: cannot resolve item '${item}'
|
||||
#
|
||||
# possible problems:
|
||||
# need more directories?
|
||||
# need to use InstallRequiredSystemLibraries?
|
||||
# run in install tree instead of build tree?
|
||||
#
|
||||
# context='${context}'
|
||||
# item='${item}'
|
||||
# exepath='${exepath}'
|
||||
# dirs='${dirs}'
|
||||
# resolved_item_var='${resolved_item_var}'
|
||||
#******************************************************************************
|
||||
#")
|
||||
endif(NOT resolved)
|
||||
|
||||
set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
|
||||
endfunction(gp_resolve_item)
|
||||
|
||||
|
||||
# gp_resolved_file_type original_file file exepath dirs type_var
|
||||
#
|
||||
# Return the type of ${file} with respect to ${original_file}. String
|
||||
# describing type of prerequisite is returned in variable named ${type_var}.
|
||||
#
|
||||
# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file}
|
||||
# values -- but only for non-embedded items.
|
||||
#
|
||||
# Possible types are:
|
||||
# system
|
||||
# local
|
||||
# embedded
|
||||
# other
|
||||
#
|
||||
function(gp_resolved_file_type original_file file exepath dirs type_var)
|
||||
#message(STATUS "**")
|
||||
|
||||
if(NOT IS_ABSOLUTE "${original_file}")
|
||||
message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
|
||||
endif()
|
||||
|
||||
set(is_embedded 0)
|
||||
set(is_local 0)
|
||||
set(is_system 0)
|
||||
|
||||
set(resolved_file "${file}")
|
||||
|
||||
if("${file}" MATCHES "^@(executable|loader)_path")
|
||||
set(is_embedded 1)
|
||||
endif()
|
||||
|
||||
if(NOT is_embedded)
|
||||
if(NOT IS_ABSOLUTE "${file}")
|
||||
gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
|
||||
endif()
|
||||
|
||||
string(TOLOWER "${original_file}" original_lower)
|
||||
string(TOLOWER "${resolved_file}" lower)
|
||||
|
||||
if(UNIX)
|
||||
if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)")
|
||||
set(is_system 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
|
||||
set(is_system 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
string(TOLOWER "$ENV{SystemRoot}" sysroot)
|
||||
string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
|
||||
|
||||
string(TOLOWER "$ENV{windir}" windir)
|
||||
string(REGEX REPLACE "\\\\" "/" windir "${windir}")
|
||||
|
||||
if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)")
|
||||
set(is_system 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT is_system)
|
||||
get_filename_component(original_path "${original_lower}" PATH)
|
||||
get_filename_component(path "${lower}" PATH)
|
||||
if("${original_path}" STREQUAL "${path}")
|
||||
set(is_local 1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Return type string based on computed booleans:
|
||||
#
|
||||
set(type "other")
|
||||
|
||||
if(is_system)
|
||||
set(type "system")
|
||||
elseif(is_embedded)
|
||||
set(type "embedded")
|
||||
elseif(is_local)
|
||||
set(type "local")
|
||||
endif()
|
||||
|
||||
#message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
|
||||
#message(STATUS " type: '${type}'")
|
||||
|
||||
if(NOT is_embedded)
|
||||
if(NOT IS_ABSOLUTE "${resolved_file}")
|
||||
if(lower MATCHES "^msvc[^/]+dll" AND is_system)
|
||||
message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
|
||||
else()
|
||||
message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(${type_var} "${type}" PARENT_SCOPE)
|
||||
|
||||
#message(STATUS "**")
|
||||
endfunction()
|
||||
|
||||
|
||||
# gp_file_type original_file file type_var
|
||||
#
|
||||
# Return the type of ${file} with respect to ${original_file}. String
|
||||
# describing type of prerequisite is returned in variable named ${type_var}.
|
||||
#
|
||||
# Possible types are:
|
||||
# system
|
||||
# local
|
||||
# embedded
|
||||
# other
|
||||
#
|
||||
function(gp_file_type original_file file type_var)
|
||||
if(NOT IS_ABSOLUTE "${original_file}")
|
||||
message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
|
||||
endif()
|
||||
|
||||
get_filename_component(exepath "${original_file}" PATH)
|
||||
|
||||
set(type "")
|
||||
gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
|
||||
|
||||
set(${type_var} "${type}" PARENT_SCOPE)
|
||||
endfunction(gp_file_type)
|
||||
|
||||
|
||||
# get_prerequisites target prerequisites_var exclude_system recurse dirs
|
||||
#
|
||||
# Get the list of shared library files required by ${target}. The list in
|
||||
# the variable named ${prerequisites_var} should be empty on first entry to
|
||||
# this function. On exit, ${prerequisites_var} will contain the list of
|
||||
# required shared library files.
|
||||
#
|
||||
# target is the full path to an executable file
|
||||
#
|
||||
# prerequisites_var is the name of a CMake variable to contain the results
|
||||
#
|
||||
# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to
|
||||
# exclude them
|
||||
#
|
||||
# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites
|
||||
# recursively
|
||||
#
|
||||
# exepath is the path to the top level executable used for @executable_path
|
||||
# replacment on the Mac
|
||||
#
|
||||
# dirs is a list of paths where libraries might be found: these paths are
|
||||
# searched first when a target without any path info is given. Then standard
|
||||
# system locations are also searched: PATH, Framework locations, /usr/lib...
|
||||
#
|
||||
function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
|
||||
set(verbose 0)
|
||||
set(eol_char "E")
|
||||
|
||||
if(NOT IS_ABSOLUTE "${target}")
|
||||
message("warning: target '${target}' is not absolute...")
|
||||
endif(NOT IS_ABSOLUTE "${target}")
|
||||
|
||||
if(NOT EXISTS "${target}")
|
||||
message("warning: target '${target}' does not exist...")
|
||||
endif(NOT EXISTS "${target}")
|
||||
|
||||
# <setup-gp_tool-vars>
|
||||
#
|
||||
# Try to choose the right tool by default. Caller can set gp_tool prior to
|
||||
# calling this function to force using a different tool.
|
||||
#
|
||||
if("${gp_tool}" STREQUAL "")
|
||||
set(gp_tool "ldd")
|
||||
if(APPLE)
|
||||
set(gp_tool "otool")
|
||||
endif(APPLE)
|
||||
if(WIN32)
|
||||
set(gp_tool "dumpbin")
|
||||
endif(WIN32)
|
||||
endif("${gp_tool}" STREQUAL "")
|
||||
|
||||
set(gp_tool_known 0)
|
||||
|
||||
if("${gp_tool}" STREQUAL "ldd")
|
||||
set(gp_cmd_args "")
|
||||
set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
|
||||
set(gp_regex_cmp_count 1)
|
||||
set(gp_tool_known 1)
|
||||
endif("${gp_tool}" STREQUAL "ldd")
|
||||
|
||||
if("${gp_tool}" STREQUAL "otool")
|
||||
set(gp_cmd_args "-L")
|
||||
set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
|
||||
set(gp_regex_cmp_count 3)
|
||||
set(gp_tool_known 1)
|
||||
endif("${gp_tool}" STREQUAL "otool")
|
||||
|
||||
if("${gp_tool}" STREQUAL "dumpbin")
|
||||
set(gp_cmd_args "/dependents")
|
||||
set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
|
||||
set(gp_regex_cmp_count 1)
|
||||
set(gp_tool_known 1)
|
||||
set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
|
||||
endif("${gp_tool}" STREQUAL "dumpbin")
|
||||
|
||||
if(NOT gp_tool_known)
|
||||
message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
|
||||
message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
|
||||
message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.")
|
||||
return()
|
||||
endif(NOT gp_tool_known)
|
||||
|
||||
set(gp_cmd_paths ${gp_cmd_paths}
|
||||
"C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
|
||||
"C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
|
||||
"C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
|
||||
"/usr/local/bin"
|
||||
"/usr/bin"
|
||||
)
|
||||
|
||||
find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
|
||||
|
||||
if(NOT gp_cmd)
|
||||
message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
|
||||
return()
|
||||
endif(NOT gp_cmd)
|
||||
|
||||
if("${gp_tool}" STREQUAL "dumpbin")
|
||||
# When running dumpbin, it also needs the "Common7/IDE" directory in the
|
||||
# PATH. It will already be in the PATH if being run from a Visual Studio
|
||||
# command prompt. Add it to the PATH here in case we are running from a
|
||||
# different command prompt.
|
||||
#
|
||||
get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
|
||||
get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
|
||||
if(EXISTS "${gp_cmd_dlls_dir}")
|
||||
# only add to the path if it is not already in the path
|
||||
if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
|
||||
set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
|
||||
endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
|
||||
endif(EXISTS "${gp_cmd_dlls_dir}")
|
||||
endif("${gp_tool}" STREQUAL "dumpbin")
|
||||
#
|
||||
# </setup-gp_tool-vars>
|
||||
|
||||
if("${gp_tool}" STREQUAL "ldd")
|
||||
set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
|
||||
foreach(dir ${exepath} ${dirs})
|
||||
set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
|
||||
endforeach(dir)
|
||||
endif("${gp_tool}" STREQUAL "ldd")
|
||||
|
||||
|
||||
# Track new prerequisites at each new level of recursion. Start with an
|
||||
# empty list at each level:
|
||||
#
|
||||
set(unseen_prereqs)
|
||||
|
||||
# Run gp_cmd on the target:
|
||||
#
|
||||
execute_process(
|
||||
COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
|
||||
OUTPUT_VARIABLE gp_cmd_ov
|
||||
)
|
||||
|
||||
if("${gp_tool}" STREQUAL "ldd")
|
||||
set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
|
||||
endif("${gp_tool}" STREQUAL "ldd")
|
||||
|
||||
if(verbose)
|
||||
message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
|
||||
message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
|
||||
message(STATUS "</RawOutput>")
|
||||
endif(verbose)
|
||||
|
||||
get_filename_component(target_dir "${target}" PATH)
|
||||
|
||||
# Convert to a list of lines:
|
||||
#
|
||||
string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
|
||||
string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
|
||||
|
||||
# Analyze each line for file names that match the regular expression:
|
||||
#
|
||||
foreach(candidate ${candidates})
|
||||
if("${candidate}" MATCHES "${gp_regex}")
|
||||
# Extract information from each candidate:
|
||||
string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
|
||||
|
||||
if(gp_regex_cmp_count GREATER 1)
|
||||
string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
|
||||
endif(gp_regex_cmp_count GREATER 1)
|
||||
|
||||
if(gp_regex_cmp_count GREATER 2)
|
||||
string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
|
||||
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
|
||||
endif(gp_regex_cmp_count GREATER 2)
|
||||
|
||||
# Use the raw_item as the list entries returned by this function. Use the
|
||||
# gp_resolve_item function to resolve it to an actual full path file if
|
||||
# necessary.
|
||||
#
|
||||
set(item "${raw_item}")
|
||||
|
||||
# Add each item unless it is excluded:
|
||||
#
|
||||
set(add_item 1)
|
||||
|
||||
if(${exclude_system})
|
||||
set(type "")
|
||||
gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
|
||||
if("${type}" STREQUAL "system")
|
||||
set(add_item 0)
|
||||
endif("${type}" STREQUAL "system")
|
||||
endif(${exclude_system})
|
||||
|
||||
if(add_item)
|
||||
list(LENGTH ${prerequisites_var} list_length_before_append)
|
||||
gp_append_unique(${prerequisites_var} "${item}")
|
||||
list(LENGTH ${prerequisites_var} list_length_after_append)
|
||||
|
||||
if(${recurse})
|
||||
# If item was really added, this is the first time we have seen it.
|
||||
# Add it to unseen_prereqs so that we can recursively add *its*
|
||||
# prerequisites...
|
||||
#
|
||||
# But first: resolve its name to an absolute full path name such
|
||||
# that the analysis tools can simply accept it as input.
|
||||
#
|
||||
if(NOT list_length_before_append EQUAL list_length_after_append)
|
||||
gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
|
||||
set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
|
||||
endif(NOT list_length_before_append EQUAL list_length_after_append)
|
||||
endif(${recurse})
|
||||
endif(add_item)
|
||||
else("${candidate}" MATCHES "${gp_regex}")
|
||||
if(verbose)
|
||||
message(STATUS "ignoring non-matching line: '${candidate}'")
|
||||
endif(verbose)
|
||||
endif("${candidate}" MATCHES "${gp_regex}")
|
||||
endforeach(candidate)
|
||||
|
||||
list(LENGTH ${prerequisites_var} prerequisites_var_length)
|
||||
if(prerequisites_var_length GREATER 0)
|
||||
list(SORT ${prerequisites_var})
|
||||
endif(prerequisites_var_length GREATER 0)
|
||||
if(${recurse})
|
||||
set(more_inputs ${unseen_prereqs})
|
||||
foreach(input ${more_inputs})
|
||||
get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
|
||||
endforeach(input)
|
||||
endif(${recurse})
|
||||
|
||||
set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
|
||||
endfunction(get_prerequisites)
|
||||
|
||||
|
||||
# list_prerequisites target all exclude_system verbose
|
||||
#
|
||||
# ARGV0 (target) is the full path to an executable file
|
||||
#
|
||||
# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only,
|
||||
# 1 for all prerequisites recursively
|
||||
#
|
||||
# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system"
|
||||
# prerequisites , 1 to exclude them
|
||||
#
|
||||
# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path
|
||||
# names of prerequisites, 1 to print extra information
|
||||
#
|
||||
function(list_prerequisites target)
|
||||
if("${ARGV1}" STREQUAL "")
|
||||
set(all 1)
|
||||
else("${ARGV1}" STREQUAL "")
|
||||
set(all "${ARGV1}")
|
||||
endif("${ARGV1}" STREQUAL "")
|
||||
|
||||
if("${ARGV2}" STREQUAL "")
|
||||
set(exclude_system 0)
|
||||
else("${ARGV2}" STREQUAL "")
|
||||
set(exclude_system "${ARGV2}")
|
||||
endif("${ARGV2}" STREQUAL "")
|
||||
|
||||
if("${ARGV3}" STREQUAL "")
|
||||
set(verbose 0)
|
||||
else("${ARGV3}" STREQUAL "")
|
||||
set(verbose "${ARGV3}")
|
||||
endif("${ARGV3}" STREQUAL "")
|
||||
|
||||
set(count 0)
|
||||
set(count_str "")
|
||||
set(print_count "${verbose}")
|
||||
set(print_prerequisite_type "${verbose}")
|
||||
set(print_target "${verbose}")
|
||||
set(type_str "")
|
||||
|
||||
get_filename_component(exepath "${target}" PATH)
|
||||
|
||||
set(prereqs "")
|
||||
get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
|
||||
|
||||
if(print_target)
|
||||
message(STATUS "File '${target}' depends on:")
|
||||
endif(print_target)
|
||||
|
||||
foreach(d ${prereqs})
|
||||
math(EXPR count "${count} + 1")
|
||||
|
||||
if(print_count)
|
||||
set(count_str "${count}. ")
|
||||
endif(print_count)
|
||||
|
||||
if(print_prerequisite_type)
|
||||
gp_file_type("${target}" "${d}" type)
|
||||
set(type_str " (${type})")
|
||||
endif(print_prerequisite_type)
|
||||
|
||||
message(STATUS "${count_str}${d}${type_str}")
|
||||
endforeach(d)
|
||||
endfunction(list_prerequisites)
|
||||
|
||||
|
||||
# list_prerequisites_by_glob glob_arg glob_exp
|
||||
#
|
||||
# glob_arg is GLOB or GLOB_RECURSE
|
||||
#
|
||||
# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list
|
||||
# of matching files. If a matching file is executable, its prerequisites are
|
||||
# listed.
|
||||
#
|
||||
# Any additional (optional) arguments provided are passed along as the
|
||||
# optional arguments to the list_prerequisites calls.
|
||||
#
|
||||
function(list_prerequisites_by_glob glob_arg glob_exp)
|
||||
message(STATUS "=============================================================================")
|
||||
message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
|
||||
message(STATUS "")
|
||||
file(${glob_arg} file_list ${glob_exp})
|
||||
foreach(f ${file_list})
|
||||
is_file_executable("${f}" is_f_executable)
|
||||
if(is_f_executable)
|
||||
message(STATUS "=============================================================================")
|
||||
list_prerequisites("${f}" ${ARGN})
|
||||
message(STATUS "")
|
||||
endif(is_f_executable)
|
||||
endforeach(f)
|
||||
endfunction(list_prerequisites_by_glob)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
set(GLUI OFF CACHE BOOL
|
||||
"GLUI support for the llplugin/llmedia test apps.")
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(glui)
|
||||
set(GLUI ON CACHE BOOL
|
||||
"GLUI support for the llplugin/llmedia test apps.")
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (LINUX)
|
||||
set(GLUI ON CACHE BOOL
|
||||
"llplugin media apps HACK for Linux.")
|
||||
endif (LINUX)
|
||||
|
||||
if (DARWIN OR LINUX)
|
||||
set(GLUI_LIBRARY
|
||||
glui)
|
||||
endif (DARWIN OR LINUX)
|
||||
|
||||
if (WINDOWS)
|
||||
set(GLUI_LIBRARY
|
||||
debug glui32.lib
|
||||
optimized glui32.lib)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(freeglut)
|
||||
set(GLUT_LIBRARY
|
||||
debug freeglut_static.lib
|
||||
optimized freeglut_static.lib)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (LINUX)
|
||||
FIND_LIBRARY(GLUT_LIBRARY glut)
|
||||
endif (LINUX)
|
||||
|
||||
if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(GLUT_LIBRARY GLUT)
|
||||
endif (DARWIN)
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
# If you want to enable or disable TCMALLOC in viewer builds, this is the place.
|
||||
# set ON or OFF as desired.
|
||||
set (USE_TCMALLOC OFF)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindGooglePerfTools)
|
||||
else (USESYSTEMLIBS)
|
||||
if (WINDOWS)
|
||||
if (USE_TCMALLOC)
|
||||
use_prebuilt_binary(gperftools)
|
||||
set(TCMALLOC_LIBRARIES
|
||||
debug libtcmalloc_minimal-debug
|
||||
optimized libtcmalloc_minimal)
|
||||
set(TCMALLOC_LINK_FLAGS "/INCLUDE:__tcmalloc")
|
||||
else (USE_TCMALLOC)
|
||||
set(TCMALLOC_LIBRARIES)
|
||||
set(TCMALLOC_LINK_FLAGS)
|
||||
endif (USE_TCMALLOC)
|
||||
set(GOOGLE_PERFTOOLS_FOUND "YES")
|
||||
endif (WINDOWS)
|
||||
if (LINUX)
|
||||
if (USE_TCMALLOC)
|
||||
use_prebuilt_binary(gperftools)
|
||||
set(TCMALLOC_LIBRARIES
|
||||
tcmalloc)
|
||||
else (USE_TCMALLOC)
|
||||
set(TCMALLOC_LIBRARIES)
|
||||
endif (USE_TCMALLOC)
|
||||
set(PROFILER_LIBRARIES profiler)
|
||||
set(GOOGLE_PERFTOOLS_INCLUDE_DIR
|
||||
${LIBS_PREBUILT_DIR}/include)
|
||||
set(GOOGLE_PERFTOOLS_FOUND "YES")
|
||||
endif (LINUX)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (GOOGLE_PERFTOOLS_FOUND)
|
||||
# XXX Disable temporarily, until we have compilation issues on 64-bit
|
||||
# Etch sorted.
|
||||
set(USE_GOOGLE_PERFTOOLS OFF CACHE BOOL "Build with Google PerfTools support.")
|
||||
endif (GOOGLE_PERFTOOLS_FOUND)
|
||||
|
||||
if (WINDOWS)
|
||||
set(USE_GOOGLE_PERFTOOLS ON)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (USE_GOOGLE_PERFTOOLS)
|
||||
if (USE_TCMALLOC)
|
||||
set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1)
|
||||
else (USE_TCMALLOC)
|
||||
set(TCMALLOC_FLAG -ULL_USE_TCMALLOC)
|
||||
endif (USE_TCMALLOC)
|
||||
endif (USE_GOOGLE_PERFTOOLS)
|
||||
|
||||
if (USE_GOOGLE_PERFTOOLS)
|
||||
include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR})
|
||||
set(GOOGLE_PERFTOOLS_LIBRARIES ${TCMALLOC_LIBRARIES} ${STACKTRACE_LIBRARIES} ${PROFILER_LIBRARIES})
|
||||
else (USE_GOOGLE_PERFTOOLS)
|
||||
endif (USE_GOOGLE_PERFTOOLS)
|
||||
|
|
@ -8,6 +8,11 @@ use_prebuilt_binary(havok-source)
|
|||
set(Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Source)
|
||||
list(APPEND Havok_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/havok/Demo)
|
||||
|
||||
# HK_DISABLE_IMPLICIT_VVECTOR3_CONVERSION suppresses an intended conversion
|
||||
# function which Xcode scolds us will unconditionally enter infinite
|
||||
# recursion if called. This hides that function.
|
||||
add_definitions("-DHK_DISABLE_IMPLICIT_VVECTOR3_CONVERSION")
|
||||
|
||||
set(HAVOK_DEBUG_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug/havok-fulldebug)
|
||||
set(HAVOK_RELEASE_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release/havok)
|
||||
|
||||
|
|
@ -49,89 +54,74 @@ unset(HK_DEBUG_LIBRARIES)
|
|||
unset(HK_RELEASE_LIBRARIES)
|
||||
unset(HK_RELWITHDEBINFO_LIBRARIES)
|
||||
|
||||
if (DEBUG_PREBUILT)
|
||||
# DEBUG_MESSAGE() displays debugging message
|
||||
function(DEBUG_MESSAGE)
|
||||
# prints message args separated by semicolons rather than spaces,
|
||||
# but making it pretty is a lot more work
|
||||
message(STATUS "${ARGN}")
|
||||
endfunction(DEBUG_MESSAGE)
|
||||
else (DEBUG_PREBUILT)
|
||||
# without DEBUG_PREBUILT, DEBUG_MESSAGE() is a no-op
|
||||
function(DEBUG_MESSAGE)
|
||||
endfunction(DEBUG_MESSAGE)
|
||||
endif (DEBUG_PREBUILT)
|
||||
|
||||
# DEBUG_EXEC() reports each execute_process() before invoking
|
||||
function(DEBUG_EXEC)
|
||||
DEBUG_MESSAGE(${ARGN})
|
||||
execute_process(COMMAND ${ARGN})
|
||||
endfunction(DEBUG_EXEC)
|
||||
|
||||
# *TODO: Figure out why we need to extract like this...
|
||||
foreach(HAVOK_LIB ${HAVOK_LIBS})
|
||||
find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH})
|
||||
find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH})
|
||||
find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH})
|
||||
|
||||
if(LINUX)
|
||||
set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
find_library(HAVOK_DEBUG_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_DEBUG_LIBRARY_PATH})
|
||||
find_library(HAVOK_RELEASE_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELEASE_LIBRARY_PATH})
|
||||
find_library(HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB} ${HAVOK_LIB} PATHS ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH})
|
||||
|
||||
if(LINUX)
|
||||
set(debug_dir "${HAVOK_DEBUG_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
set(release_dir "${HAVOK_RELEASE_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
set(relwithdebinfo_dir "${HAVOK_RELWITHDEBINFO_LIBRARY_PATH}/${HAVOK_LIB}")
|
||||
|
||||
# Try to avoid extracting havok library each time we run cmake.
|
||||
if("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted")
|
||||
file(READ ${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted "havok_${HAVOK_LIB}_extracted")
|
||||
if(DEBUG_PREBUILT)
|
||||
message(STATUS "havok_${HAVOK_LIB}_extracted: \"${havok_${HAVOK_LIB}_extracted}\"")
|
||||
endif(DEBUG_PREBUILT)
|
||||
DEBUG_MESSAGE("havok_${HAVOK_LIB}_extracted: \"${havok_${HAVOK_LIB}_extracted}\"")
|
||||
endif("${havok_${HAVOK_LIB}_extracted}" STREQUAL "" AND EXISTS "${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted")
|
||||
|
||||
if(${PREBUILD_TRACKING_DIR}/havok_source_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0)
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "Extracting ${HAVOK_LIB}...")
|
||||
endif(DEBUG_PREBUILT)
|
||||
set(cmd "mkdir")
|
||||
DEBUG_MESSAGE("Extracting ${HAVOK_LIB}...")
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "${cmd} ${debug_dir}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${HAVOK_DEBUG_LIBRARY_PATH} ARGS ${debug_dir} OUTPUT_VARIABLE rv)
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "${cmd} ${release_dir}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${HAVOK_RELEASE_LIBRARY_PATH} ARGS ${release_dir} OUTPUT_VARIABLE rv)
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "${cmd} ${relwithdebinfo_dir}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${HAVOK_RELWITHDEBINFO_LIBRARY_PATH} ARGS ${relwithdebinfo_dir} OUTPUT_VARIABLE rv)
|
||||
|
||||
set(cmd "ar")
|
||||
set(arg " -xv")
|
||||
set(arg "${arg} ../lib${HAVOK_LIB}.a")
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "cd ${debug_dir} && ${cmd} ${arg}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${debug_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "cd ${release_dir} && ${cmd} ${arg}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${release_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "cd ${relwithdebinfo_dir} && ${cmd} ${arg}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
exec_program( ${cmd} ${relwithdebinfo_dir} ARGS ${arg} OUTPUT_VARIABLE rv)
|
||||
foreach(lib ${debug_dir} ${release_dir} ${relwithdebinfo_dir})
|
||||
DEBUG_EXEC("mkdir" ${lib})
|
||||
DEBUG_EXEC("ar" "-xv" "../lib${HAVOK_LIB}.a"
|
||||
WORKING_DIRECTORY ${lib})
|
||||
endforeach(lib)
|
||||
|
||||
# Just assume success for now.
|
||||
set(havok_${HAVOK_LIB}_extracted 0)
|
||||
file(WRITE ${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted "${havok_${HAVOK_LIB}_extracted}")
|
||||
|
||||
endif(${PREBUILD_TRACKING_DIR}/havok_source_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/havok_${HAVOK_LIB}_extracted OR NOT ${havok_${HAVOK_LIB}_extracted} EQUAL 0)
|
||||
endif()
|
||||
|
||||
file(GLOB extracted_debug "${debug_dir}/*.o")
|
||||
file(GLOB extracted_release "${release_dir}/*.o")
|
||||
file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o")
|
||||
file(GLOB extracted_debug "${debug_dir}/*.o")
|
||||
file(GLOB extracted_release "${release_dir}/*.o")
|
||||
file(GLOB extracted_relwithdebinfo "${relwithdebinfo_dir}/*.o")
|
||||
|
||||
if(DEBUG_PREBUILT)
|
||||
MESSAGE(STATUS "extracted_debug ${debug_dir}/*.o")
|
||||
MESSAGE(STATUS "extracted_release ${release_dir}/*.o")
|
||||
MESSAGE(STATUS "extracted_relwithdebinfo ${relwithdebinfo_dir}/*.o")
|
||||
endif(DEBUG_PREBUILT)
|
||||
DEBUG_MESSAGE("extracted_debug ${debug_dir}/*.o")
|
||||
DEBUG_MESSAGE("extracted_release ${release_dir}/*.o")
|
||||
DEBUG_MESSAGE("extracted_relwithdebinfo ${relwithdebinfo_dir}/*.o")
|
||||
|
||||
list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug})
|
||||
list(APPEND HK_RELEASE_LIBRARIES ${extracted_release})
|
||||
list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo})
|
||||
else(LINUX)
|
||||
# Win32
|
||||
list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}})
|
||||
list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}})
|
||||
list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}})
|
||||
endif (LINUX)
|
||||
list(APPEND HK_DEBUG_LIBRARIES ${extracted_debug})
|
||||
list(APPEND HK_RELEASE_LIBRARIES ${extracted_release})
|
||||
list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${extracted_relwithdebinfo})
|
||||
else(LINUX)
|
||||
# Win32
|
||||
list(APPEND HK_DEBUG_LIBRARIES ${HAVOK_DEBUG_LIB_${HAVOK_LIB}})
|
||||
list(APPEND HK_RELEASE_LIBRARIES ${HAVOK_RELEASE_LIB_${HAVOK_LIB}})
|
||||
list(APPEND HK_RELWITHDEBINFO_LIBRARIES ${HAVOK_RELWITHDEBINFO_LIB_${HAVOK_LIB}})
|
||||
endif (LINUX)
|
||||
endforeach(HAVOK_LIB)
|
||||
|
||||
endif(NOT DEFINED ${CMAKE_CURRENT_LIST_FILE}_INCLUDED)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ else (USESYSTEMLIBS)
|
|||
if (WINDOWS)
|
||||
set(HUNSPELL_LIBRARY libhunspell)
|
||||
elseif(DARWIN)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3.0)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
elseif(LINUX)
|
||||
set(HUNSPELL_LIBRARY hunspell-1.3)
|
||||
else()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ include(LLTestCommand)
|
|||
include(GoogleMock)
|
||||
include(Tut)
|
||||
|
||||
#*****************************************************************************
|
||||
# LL_ADD_PROJECT_UNIT_TESTS
|
||||
#*****************************************************************************
|
||||
MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
|
||||
# Given a project name and a list of sourcefiles (with optional properties on each),
|
||||
# add targets to build and run the tests specified.
|
||||
|
|
@ -35,7 +38,6 @@ INCLUDE(GoogleMock)
|
|||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
llcommon
|
||||
llcorehttp
|
||||
)
|
||||
IF(NOT "${project}" STREQUAL "llmath")
|
||||
# add llmath as a dep unless the tested module *is* llmath!
|
||||
|
|
@ -75,19 +77,17 @@ INCLUDE(GoogleMock)
|
|||
# Per-codefile additional / external source, header, and include dir property extraction
|
||||
#
|
||||
# Source
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
|
||||
IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_SOURCE_FILES "")
|
||||
ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
|
||||
SET(${name}_test_SOURCE_FILES
|
||||
${source}
|
||||
tests/${name}_test.${extension}
|
||||
${alltest_SOURCE_FILES}
|
||||
${${name}_test_additional_SOURCE_FILES} )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Headers
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
|
||||
IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_HEADER_FILES "")
|
||||
ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
|
||||
SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
|
||||
set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
|
||||
|
|
@ -95,10 +95,7 @@ INCLUDE(GoogleMock)
|
|||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Include dirs
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
|
||||
IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_INCLUDE_DIRS "")
|
||||
ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
|
||||
INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${${name}_test_additional_INCLUDE_DIRS} )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
|
||||
|
|
@ -114,15 +111,9 @@ INCLUDE(GoogleMock)
|
|||
#
|
||||
# WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
|
||||
# Projects
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
|
||||
IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_PROJECTS "")
|
||||
ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
|
||||
# Libraries
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
|
||||
IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_LIBRARIES "")
|
||||
ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
|
||||
|
|
@ -130,13 +121,14 @@ INCLUDE(GoogleMock)
|
|||
# Add to project
|
||||
TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
|
||||
# Compile-time Definitions
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
|
||||
IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
|
||||
SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
|
||||
GET_OPT_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
|
||||
SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name}
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${${name}_test_additional_CFLAGS}"
|
||||
COMPILE_DEFINITIONS "LL_TEST=${name};LL_TEST_${name}")
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
|
||||
#
|
||||
# Setup test targets
|
||||
|
|
@ -176,6 +168,19 @@ INCLUDE(GoogleMock)
|
|||
ADD_DEPENDENCIES(${project} ${project}_tests)
|
||||
ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
|
||||
|
||||
#*****************************************************************************
|
||||
# GET_OPT_SOURCE_FILE_PROPERTY
|
||||
#*****************************************************************************
|
||||
MACRO(GET_OPT_SOURCE_FILE_PROPERTY var filename property)
|
||||
GET_SOURCE_FILE_PROPERTY(${var} "${filename}" "${property}")
|
||||
IF("${${var}}" MATCHES NOTFOUND)
|
||||
SET(${var} "")
|
||||
ENDIF("${${var}}" MATCHES NOTFOUND)
|
||||
ENDMACRO(GET_OPT_SOURCE_FILE_PROPERTY)
|
||||
|
||||
#*****************************************************************************
|
||||
# LL_ADD_INTEGRATION_TEST
|
||||
#*****************************************************************************
|
||||
FUNCTION(LL_ADD_INTEGRATION_TEST
|
||||
testname
|
||||
additional_source_files
|
||||
|
|
@ -185,7 +190,7 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
|
|||
if(TEST_DEBUG)
|
||||
message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
|
||||
endif(TEST_DEBUG)
|
||||
|
||||
|
||||
SET(source_files
|
||||
tests/${testname}_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
|
|
@ -207,7 +212,11 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
|
|||
message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
|
||||
endif(TEST_DEBUG)
|
||||
ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
|
||||
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
|
||||
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}"
|
||||
COMPILE_DEFINITIONS "LL_TEST=${testname};LL_TEST_${testname}"
|
||||
)
|
||||
|
||||
if(USESYSTEMLIBS)
|
||||
SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
|
||||
|
|
@ -269,6 +278,9 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
|
|||
|
||||
ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
|
||||
|
||||
#*****************************************************************************
|
||||
# SET_TEST_PATH
|
||||
#*****************************************************************************
|
||||
MACRO(SET_TEST_PATH LISTVAR)
|
||||
IF(WINDOWS)
|
||||
# We typically build/package only Release variants of third-party
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
use_prebuilt_binary(llbase)
|
||||
|
|
@ -4,7 +4,6 @@ include(APR)
|
|||
include(Boost)
|
||||
include(EXPAT)
|
||||
include(ZLIB)
|
||||
include(GooglePerfTools)
|
||||
|
||||
set(LLCOMMON_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llcommon
|
||||
|
|
@ -34,8 +33,6 @@ else (LINUX)
|
|||
${BOOST_SYSTEM_LIBRARY} )
|
||||
endif (LINUX)
|
||||
|
||||
# add_definitions(${TCMALLOC_FLAG})
|
||||
|
||||
set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a static library.")
|
||||
if(LLCOMMON_LINK_SHARED)
|
||||
add_definitions(-DLL_COMMON_LINK_SHARED=1)
|
||||
|
|
|
|||
|
|
@ -3,35 +3,38 @@
|
|||
macro(ll_deploy_sharedlibs_command target_exe)
|
||||
set(TARGET_LOCATION $<TARGET_FILE:${target_exe}>)
|
||||
get_filename_component(OUTPUT_PATH ${TARGET_LOCATION} PATH)
|
||||
|
||||
if(DARWIN)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE)
|
||||
if(IS_BUNDLE)
|
||||
# If its a bundle the exe is not in the target location, this should find it.
|
||||
get_filename_component(TARGET_FILE ${TARGET_LOCATION} NAME)
|
||||
set(OUTPUT_PATH ${TARGET_LOCATION}.app/Contents/MacOS)
|
||||
set(TARGET_LOCATION ${OUTPUT_PATH}/${TARGET_FILE})
|
||||
set(OUTPUT_PATH ${OUTPUT_PATH}/../Resources)
|
||||
endif(IS_BUNDLE)
|
||||
elseif(WINDOWS)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
LIST(APPEND SEARCH_DIRS "$ENV{SystemRoot}/system32")
|
||||
elseif(LINUX)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
set(OUTPUT_PATH ${OUTPUT_PATH}/lib)
|
||||
endif(DARWIN)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${target_exe} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
"-DBIN_NAME=\"${TARGET_LOCATION}\""
|
||||
"-DSEARCH_DIRS=\"${SEARCH_DIRS}\""
|
||||
"-DDST_PATH=\"${OUTPUT_PATH}\""
|
||||
"-P"
|
||||
"${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake"
|
||||
)
|
||||
# It's not clear that this does anything useful for us on Darwin. It has
|
||||
# been broken for some time now; the BIN_NAME was being constructed as a
|
||||
# ridiculous nonexistent path with duplicated segments. Fixing that only
|
||||
# produces ominous spammy warnings: at the time the command below is run, we
|
||||
# have not yet populated the nested mac-crash-logger.app/Contents/Resources
|
||||
# with the .dylibs with which it was linked. Moreover, the form of the
|
||||
# embedded @executable_path/../Resources/mumble.dylib pathname confuses the
|
||||
# GetPrerequisites.cmake tool invoked by DeploySharedLibs.cmake. It seems
|
||||
# clear that we have long since accomplished by other means what this was
|
||||
# originally supposed to do. Skipping it only eliminates an annoying
|
||||
# non-fatal error.
|
||||
if(NOT DARWIN)
|
||||
if(WINDOWS)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
LIST(APPEND SEARCH_DIRS "$ENV{SystemRoot}/system32")
|
||||
elseif(LINUX)
|
||||
SET_TEST_PATH(SEARCH_DIRS)
|
||||
set(OUTPUT_PATH ${OUTPUT_PATH}/lib)
|
||||
endif(WINDOWS)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${target_exe} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
"-DBIN_NAME=\"${TARGET_LOCATION}\""
|
||||
"-DSEARCH_DIRS=\"${SEARCH_DIRS}\""
|
||||
"-DDST_PATH=\"${OUTPUT_PATH}\""
|
||||
"-P"
|
||||
"${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake"
|
||||
)
|
||||
endif(NOT DARWIN)
|
||||
|
||||
endmacro(ll_deploy_sharedlibs_command)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ if (WINDOWS)
|
|||
libvlccore.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(VLC_PLUGIN_LIBRARIES
|
||||
libvlc.dylib
|
||||
libvlccore.dylib
|
||||
)
|
||||
elseif (LINUX)
|
||||
# Specify a full path to make sure we get a static link
|
||||
set(VLC_PLUGIN_LIBRARIES
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
include(Prebuilt)
|
||||
|
||||
set(NGHTTP2_FIND_QUIETLY ON)
|
||||
set(NGHTTP2_FIND_REQUIRED ON)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
include(FindNGHTTP2)
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(nghttp2)
|
||||
if (WINDOWS)
|
||||
set(NGHTTP2_LIBRARIES
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/nghttp2.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(NGHTTP2_LIBRARIES libnghttp2.dylib)
|
||||
else (WINDOWS)
|
||||
set(NGHTTP2_LIBRARIES libnghttp2.a)
|
||||
endif (WINDOWS)
|
||||
set(NGHTTP2_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/nghttp2)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
|
@ -39,7 +39,7 @@ macro (use_prebuilt_binary _binary)
|
|||
|
||||
if(${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0)
|
||||
if(DEBUG_PREBUILT)
|
||||
message("cd ${CMAKE_SOURCE_DIR} && ${AUTOBUILD_EXECUTABLE} install
|
||||
message(STATUS "cd ${CMAKE_SOURCE_DIR} && ${AUTOBUILD_EXECUTABLE} install
|
||||
--install-dir=${AUTOBUILD_INSTALL_DIR}
|
||||
${_binary} ")
|
||||
endif(DEBUG_PREBUILT)
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
if(INSTALL_PROPRIETARY)
|
||||
include(Prebuilt)
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(quicktime)
|
||||
endif (WINDOWS)
|
||||
endif(INSTALL_PROPRIETARY)
|
||||
|
||||
if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(QUICKTIME_LIBRARY QuickTime)
|
||||
elseif (WINDOWS)
|
||||
set(QUICKTIME_SDK_DIR "$ENV{PROGRAMFILES}/QuickTime SDK"
|
||||
CACHE PATH "Location of the QuickTime SDK.")
|
||||
|
||||
find_library(DEBUG_QUICKTIME_LIBRARY qtmlclient.lib
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_DEBUG}
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
find_library(RELEASE_QUICKTIME_LIBRARY qtmlclient.lib
|
||||
PATHS
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}
|
||||
"${QUICKTIME_SDK_DIR}\\libraries"
|
||||
)
|
||||
|
||||
if (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
|
||||
set(QUICKTIME_LIBRARY
|
||||
optimized ${RELEASE_QUICKTIME_LIBRARY}
|
||||
debug ${DEBUG_QUICKTIME_LIBRARY}
|
||||
)
|
||||
|
||||
endif (DEBUG_QUICKTIME_LIBRARY AND RELEASE_QUICKTIME_LIBRARY)
|
||||
|
||||
include_directories(
|
||||
${LIBS_PREBUILT_DIR}/include/quicktime
|
||||
"${QUICKTIME_SDK_DIR}\\CIncludes"
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
mark_as_advanced(QUICKTIME_LIBRARY)
|
||||
|
||||
if (QUICKTIME_LIBRARY)
|
||||
set(QUICKTIME ON CACHE BOOL "Build with QuickTime streaming media support.")
|
||||
endif (QUICKTIME_LIBRARY)
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
if (DARWIN)
|
||||
include (Prebuilt)
|
||||
use_prebuilt_binary(requests)
|
||||
use_prebuilt_binary(urllib3)
|
||||
use_prebuilt_binary(chardet)
|
||||
use_prebuilt_binary(idna)
|
||||
endif (DARWIN)
|
||||
|
|
@ -32,9 +32,9 @@ if (USESYSTEMLIBS)
|
|||
add_definitions(${${pkg}_CFLAGS_OTHERS})
|
||||
endforeach(pkg)
|
||||
else (USESYSTEMLIBS)
|
||||
if (LINUX OR WINDOWS)
|
||||
if (LINUX)
|
||||
use_prebuilt_binary(gtk-atk-pango-glib)
|
||||
endif (LINUX OR WINDOWS)
|
||||
endif (LINUX)
|
||||
|
||||
if (LINUX)
|
||||
set(UI_LIBRARIES
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
# LINUX - Linux
|
||||
# WINDOWS - Windows
|
||||
|
||||
# Switches set here and in 00-Common.cmake must agree with
|
||||
# https://bitbucket.org/lindenlab/viewer-build-variables/src/tip/variables
|
||||
# Reading $LL_BUILD is an attempt to directly use those switches.
|
||||
if ("$ENV{LL_BUILD}" STREQUAL "")
|
||||
message(FATAL_ERROR "Environment variable LL_BUILD must be set")
|
||||
endif ()
|
||||
|
||||
# Relative and absolute paths to subtrees.
|
||||
|
||||
|
|
@ -60,46 +66,55 @@ if (NOT CMAKE_BUILD_TYPE)
|
|||
"Build type. One of: Debug Release RelWithDebInfo" FORCE)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# If someone has specified an address size, use that to determine the
|
||||
# architecture. Otherwise, let the architecture specify the address size.
|
||||
if (ADDRESS_SIZE EQUAL 32)
|
||||
#message(STATUS "ADDRESS_SIZE is 32")
|
||||
set(ARCH i686)
|
||||
elseif (ADDRESS_SIZE EQUAL 64)
|
||||
#message(STATUS "ADDRESS_SIZE is 64")
|
||||
set(ARCH x86_64)
|
||||
else (ADDRESS_SIZE EQUAL 32)
|
||||
#message(STATUS "ADDRESS_SIZE is UNRECOGNIZED: '${ADDRESS_SIZE}'")
|
||||
# Use Python's platform.machine() since uname -m isn't available everywhere.
|
||||
# Even if you can assume cygwin uname -m, the answer depends on whether
|
||||
# you're running 32-bit cygwin or 64-bit cygwin! But even 32-bit Python will
|
||||
# report a 64-bit processor.
|
||||
execute_process(COMMAND
|
||||
"${PYTHON_EXECUTABLE}" "-c"
|
||||
"import platform; print platform.machine()"
|
||||
OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
# We expect values of the form i386, i686, x86_64, AMD64.
|
||||
# In CMake, expressing ARCH.endswith('64') is awkward:
|
||||
string(LENGTH "${ARCH}" ARCH_LENGTH)
|
||||
math(EXPR ARCH_LEN_2 "${ARCH_LENGTH} - 2")
|
||||
string(SUBSTRING "${ARCH}" ${ARCH_LEN_2} 2 ARCH_LAST_2)
|
||||
if (ARCH_LAST_2 STREQUAL 64)
|
||||
#message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}")
|
||||
set(ADDRESS_SIZE 64)
|
||||
else ()
|
||||
#message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}")
|
||||
set(ADDRESS_SIZE 32)
|
||||
endif ()
|
||||
endif (ADDRESS_SIZE EQUAL 32)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(WINDOWS ON BOOL FORCE)
|
||||
set(ARCH i686)
|
||||
set(LL_ARCH ${ARCH}_win32)
|
||||
set(LL_ARCH_DIR ${ARCH}-win32)
|
||||
set(WORD_SIZE 32)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(LINUX ON BOOl FORCE)
|
||||
|
||||
# If someone has specified a word size, use that to determine the
|
||||
# architecture. Otherwise, let the architecture specify the word size.
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
#message(STATUS "WORD_SIZE is 32")
|
||||
set(ARCH i686)
|
||||
elseif (WORD_SIZE EQUAL 64)
|
||||
#message(STATUS "WORD_SIZE is 64")
|
||||
set(ARCH x86_64)
|
||||
else (WORD_SIZE EQUAL 32)
|
||||
#message(STATUS "WORD_SIZE is UNDEFINED")
|
||||
execute_process(COMMAND uname -m COMMAND sed s/i.86/i686/
|
||||
OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (ARCH STREQUAL x86_64)
|
||||
#message(STATUS "ARCH is detected as 64; ARCH is ${ARCH}")
|
||||
set(WORD_SIZE 64)
|
||||
else (ARCH STREQUAL x86_64)
|
||||
#message(STATUS "ARCH is detected as 32; ARCH is ${ARCH}")
|
||||
set(WORD_SIZE 32)
|
||||
endif (ARCH STREQUAL x86_64)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
|
||||
if (WORD_SIZE EQUAL 32)
|
||||
if (ADDRESS_SIZE EQUAL 32)
|
||||
set(DEB_ARCHITECTURE i386)
|
||||
set(FIND_LIBRARY_USE_LIB64_PATHS OFF)
|
||||
set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib32 ${CMAKE_SYSTEM_LIBRARY_PATH})
|
||||
else (WORD_SIZE EQUAL 32)
|
||||
else (ADDRESS_SIZE EQUAL 32)
|
||||
set(DEB_ARCHITECTURE amd64)
|
||||
set(FIND_LIBRARY_USE_LIB64_PATHS ON)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
endif (ADDRESS_SIZE EQUAL 32)
|
||||
|
||||
execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH
|
||||
RESULT_VARIABLE DPKG_RESULT
|
||||
|
|
@ -129,29 +144,59 @@ endif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(DARWIN 1)
|
||||
|
||||
# now we only support Xcode 7.0 using 10.11 (El Capitan), minimum OS 10.7 (Lion)
|
||||
|
||||
string(REGEX MATCH "-mmacosx-version-min=([^ ]+)" scratch "$ENV{LL_BUILD}")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "${CMAKE_MATCH_1}")
|
||||
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET = '${CMAKE_OSX_DEPLOYMENT_TARGET}'")
|
||||
|
||||
string(REGEX MATCH "-stdlib=([^ ]+)" scratch "$ENV{LL_BUILD}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "${CMAKE_MATCH_1}")
|
||||
message(STATUS "CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY = '${CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY}'")
|
||||
|
||||
string(REGEX MATCH " -g([^ ]*)" scratch "$ENV{LL_BUILD}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "${CMAKE_MATCH_1}")
|
||||
# -gdwarf-2 is passed in LL_BUILD according to 00-COMPILE-LINK-RUN.txt.
|
||||
# However, when CMake 3.9.2 sees -gdwarf-2, it silently deletes the whole -g
|
||||
# switch, producing no symbols at all! The same thing happens if we specify
|
||||
# plain -g ourselves, i.e. CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT is
|
||||
# the empty string. Specifying -gdwarf-with-dsym or just -gdwarf drives a
|
||||
# different CMake behavior: it substitutes plain -g. As of 2017-09-19,
|
||||
# viewer-build-variables/variables still passes -gdwarf-2, which is the
|
||||
# no-symbols case. Set -gdwarf, triggering CMake to substitute plain -g --
|
||||
# at least that way we should get symbols, albeit mangled ones. It Would Be
|
||||
# Nice if CMake's behavior could be predicted from a consistent mental
|
||||
# model, instead of only observed experimentally.
|
||||
string(REPLACE "dwarf-2" "dwarf"
|
||||
CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT
|
||||
"${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}")
|
||||
message(STATUS "CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT = '${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}'")
|
||||
|
||||
string(REGEX MATCH "-O([^ ]*)" scratch "$ENV{LL_BUILD}")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL "${CMAKE_MATCH_1}")
|
||||
message(STATUS "CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL = '${CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL}'")
|
||||
|
||||
string(REGEX MATCHALL "[^ ]+" LL_BUILD_LIST "$ENV{LL_BUILD}")
|
||||
list(FIND LL_BUILD_LIST "-iwithsysroot" sysroot_idx)
|
||||
if ("${sysroot_idx}" LESS 0)
|
||||
message(FATAL_ERROR "Environment variable LL_BUILD must contain '-iwithsysroot'")
|
||||
endif ()
|
||||
math(EXPR sysroot_idx "${sysroot_idx} + 1")
|
||||
list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
|
||||
message(STATUS "CMAKE_OSX_SYSROOT = '${CMAKE_OSX_SYSROOT}'")
|
||||
|
||||
set(XCODE_VERSION 7.0)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.7)
|
||||
set(CMAKE_OSX_SYSROOT macosx10.11)
|
||||
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL 3)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
|
||||
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++")
|
||||
set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT dwarf-with-dsym)
|
||||
|
||||
# Build only for i386 by default, system default on MacOSX 10.6+ is x86_64
|
||||
if (NOT CMAKE_OSX_ARCHITECTURES)
|
||||
set(CMAKE_OSX_ARCHITECTURES "i386")
|
||||
endif (NOT CMAKE_OSX_ARCHITECTURES)
|
||||
set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
|
||||
string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
|
||||
string(REPLACE "AMD64" "x86_64" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
|
||||
|
||||
set(ARCH ${CMAKE_OSX_ARCHITECTURES})
|
||||
set(LL_ARCH ${ARCH}_darwin)
|
||||
set(LL_ARCH_DIR universal-darwin)
|
||||
set(WORD_SIZE 32)
|
||||
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
|
||||
# Default deploy grid
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
include (Prebuilt)
|
||||
use_prebuilt_binary(viewer-manager)
|
||||
|
||||
|
|
@ -51,11 +51,13 @@ import HTMLParser
|
|||
import re
|
||||
import signal
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
def main(command, libpath=[], vars={}):
|
||||
def main(command, arguments=[], libpath=[], vars={}):
|
||||
"""Pass:
|
||||
command is a sequence (e.g. a list) of strings. The first item in the list
|
||||
must be the command name, the rest are its arguments.
|
||||
command is the command to be executed
|
||||
|
||||
argument is a sequence (e.g. a list) of strings to be passed to command
|
||||
|
||||
libpath is a sequence of directory pathnames. These will be appended to
|
||||
the platform-specific dynamic library search path environment variable.
|
||||
|
|
@ -85,7 +87,7 @@ def main(command, libpath=[], vars={}):
|
|||
# might not exist; instead of KeyError, just use an empty string.
|
||||
dirs = os.environ.get(var, "").split(os.pathsep)
|
||||
# Append the sequence in libpath
|
||||
print "%s += %r" % (var, libpath)
|
||||
log.info("%s += %r" % (var, libpath))
|
||||
for dir in libpath:
|
||||
# append system paths at the end
|
||||
if dir in ('/lib', '/usr/lib'):
|
||||
|
|
@ -103,20 +105,20 @@ def main(command, libpath=[], vars={}):
|
|||
# Now rebuild the path string. This way we use a minimum of separators
|
||||
# -- and we avoid adding a pointless separator when libpath is empty.
|
||||
os.environ[var] = os.pathsep.join(clean_dirs)
|
||||
print "%s = %r" % (var, os.environ[var])
|
||||
log.info("%s = %r" % (var, os.environ[var]))
|
||||
# Now handle arbitrary environment variables. The tricky part is ensuring
|
||||
# that all the keys and values we try to pass are actually strings.
|
||||
if vars:
|
||||
print "Setting:"
|
||||
for key, value in vars.iteritems():
|
||||
print "%s=%s" % (key, value)
|
||||
log.info("Setting: %s" % ("\n".join(["%s=%s" % (key, value) for key, value in vars.iteritems()])))
|
||||
os.environ.update(dict([(str(key), str(value)) for key, value in vars.iteritems()]))
|
||||
# Run the child process.
|
||||
print "Running: %s" % " ".join(command)
|
||||
command_list = [command]
|
||||
command_list.extend(arguments)
|
||||
log.info("Running: %s" % " ".join(command_list))
|
||||
# Make sure we see all relevant output *before* child-process output.
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
return subprocess.call(command)
|
||||
return subprocess.call(command_list)
|
||||
except OSError as err:
|
||||
# If the caller is trying to execute a test program that doesn't
|
||||
# exist, we want to produce a reasonable error message rather than a
|
||||
|
|
@ -126,9 +128,9 @@ def main(command, libpath=[], vars={}):
|
|||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
# In practice, the pathnames into CMake's build tree are so long as to
|
||||
# obscure the name of the test program. Just print its basename.
|
||||
print "No such program %s; check for preceding build errors" % \
|
||||
os.path.basename(command[0])
|
||||
# obscure the name of the test program. Just log its basename.
|
||||
log.warn("No such program %s; check for preceding build errors" % \
|
||||
os.path.basename(command[0]))
|
||||
# What rc should we simulate for missing executable? Windows produces
|
||||
# 9009.
|
||||
return 9009
|
||||
|
|
@ -172,10 +174,10 @@ def translate_rc(rc):
|
|||
table = get_windows_table()
|
||||
symbol, desc = table[hexrc]
|
||||
except Exception, err:
|
||||
print >>sys.stderr, "(%s -- carrying on)" % err
|
||||
return "terminated with rc %s (%s)" % (rc, hexrc)
|
||||
log.error("(%s -- carrying on)" % err)
|
||||
log.error("terminated with rc %s (%s)" % (rc, hexrc))
|
||||
else:
|
||||
return "terminated with rc %s: %s: %s" % (hexrc, symbol, desc)
|
||||
log.info("terminated with rc %s: %s: %s" % (hexrc, symbol, desc))
|
||||
|
||||
else:
|
||||
# On Posix, negative rc means the child was terminated by signal -rc.
|
||||
|
|
@ -303,22 +305,26 @@ def get_windows_table():
|
|||
|
||||
return _windows_table
|
||||
|
||||
log=logging.getLogger(__name__)
|
||||
logging.basicConfig()
|
||||
|
||||
if __name__ == "__main__":
|
||||
from optparse import OptionParser
|
||||
parser = OptionParser(usage="usage: %prog [options] command args...")
|
||||
# We want optparse support for the options we ourselves handle -- but we
|
||||
# DO NOT want it looking at options for the executable we intend to run,
|
||||
# rejecting them as invalid because we don't define them. So configure the
|
||||
# parser to stop looking for options as soon as it sees the first
|
||||
# positional argument (traditional Unix syntax).
|
||||
parser.disable_interspersed_args()
|
||||
parser.add_option("-D", "--define", dest="vars", default=[], action="append",
|
||||
metavar="VAR=value",
|
||||
help="Add VAR=value to the env variables defined")
|
||||
parser.add_option("-l", "--libpath", dest="libpath", default=[], action="append",
|
||||
metavar="DIR",
|
||||
help="Add DIR to the platform-dependent DLL search path")
|
||||
opts, args = parser.parse_args()
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-d", "--debug", dest="loglevel", action="store_const",
|
||||
const=logging.DEBUG, default=logging.INFO)
|
||||
parser.add_argument("-D", "--define", dest="vars", default=[], action="append",
|
||||
metavar="VAR=value",
|
||||
help="Add VAR=value to the env variables defined")
|
||||
parser.add_argument("-l", "--libpath", dest="libpath", default=[], action="append",
|
||||
metavar="DIR",
|
||||
help="Add DIR to the platform-dependent DLL search path")
|
||||
parser.add_argument("command")
|
||||
parser.add_argument('args', nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
|
||||
log.setLevel(args.loglevel)
|
||||
|
||||
# What we have in opts.vars is a list of strings of the form "VAR=value"
|
||||
# or possibly just "VAR". What we want is a dict. We can build that dict by
|
||||
# constructing a list of ["VAR", "value"] pairs -- so split each
|
||||
|
|
@ -326,9 +332,9 @@ if __name__ == "__main__":
|
|||
# "VAR=some=user=string"). To handle the case of just "VAR", append "" to
|
||||
# the list returned by split(), then slice off anything after the pair we
|
||||
# want.
|
||||
rc = main(command=args, libpath=opts.libpath,
|
||||
vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars]))
|
||||
rc = main(command=args.command, arguments=args.args, libpath=args.libpath,
|
||||
vars=dict([(pair.split('=', 1) + [""])[:2] for pair in args.vars]))
|
||||
if rc not in (None, 0):
|
||||
print >>sys.stderr, "Failure running: %s" % " ".join(args)
|
||||
print >>sys.stderr, "Error %s: %s" % (rc, translate_rc(rc))
|
||||
log.error("Failure running: %s" % " ".join([args.command] + args.args))
|
||||
log.error("Error %s: %s" % (rc, translate_rc(rc)))
|
||||
sys.exit((rc < 0) and 255 or rc)
|
||||
|
|
|
|||
|
|
@ -104,21 +104,23 @@ add_custom_command(TARGET llimage_libtest POST_BUILD
|
|||
if (DARWIN)
|
||||
# Copy the required libraries to the package app
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib
|
||||
)
|
||||
foreach(expat ${EXPAT_COPY})
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat} ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat}
|
||||
)
|
||||
endforeach(expat)
|
||||
endif (DARWIN)
|
||||
|
||||
if (WINDOWS)
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@ import subprocess
|
|||
|
||||
class ManifestError(RuntimeError):
|
||||
"""Use an exception more specific than generic Python RuntimeError"""
|
||||
pass
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
super(ManifestError, self).__init__(self.msg)
|
||||
|
||||
class MissingError(ManifestError):
|
||||
"""You specified a file that doesn't exist"""
|
||||
|
|
@ -143,6 +145,9 @@ ARGUMENTS=[
|
|||
default=None),
|
||||
dict(name='versionfile',
|
||||
description="""The name of a file containing the full version number."""),
|
||||
dict(name='bundleid',
|
||||
description="""The Mac OS X Bundle identifier.""",
|
||||
default="com.secondlife.indra.viewer"),
|
||||
dict(name='signature',
|
||||
description="""This specifies an identity to sign the viewer with, if any.
|
||||
If no value is supplied, the default signature will be used, if any. Currently
|
||||
|
|
@ -306,8 +311,11 @@ def main():
|
|||
continue
|
||||
if touch:
|
||||
print 'Creating additional package for "', package_id, '" in ', args['dest']
|
||||
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
|
||||
wm.do(*args['actions'])
|
||||
try:
|
||||
wm = LLManifest.for_platform(args['platform'], args.get('arch'))(args)
|
||||
wm.do(*args['actions'])
|
||||
except Exception as err:
|
||||
sys.exit(str(err))
|
||||
if touch:
|
||||
print 'Created additional package ', wm.package_file, ' for ', package_id
|
||||
faketouch = base_touch_prefix + '/' + package_id + '/' + base_touch_postfix
|
||||
|
|
@ -368,12 +376,30 @@ class LLManifest(object):
|
|||
self.excludes.append(glob)
|
||||
|
||||
def prefix(self, src='', build=None, dst=None):
|
||||
""" Pushes a prefix onto the stack. Until end_prefix is
|
||||
called, all relevant method calls (esp. to path()) will prefix
|
||||
paths with the entire prefix stack. Source and destination
|
||||
prefixes can be different, though if only one is provided they
|
||||
are both equal. To specify a no-op, use an empty string, not
|
||||
None."""
|
||||
"""
|
||||
Usage:
|
||||
|
||||
with self.prefix(...args as described...):
|
||||
self.path(...)
|
||||
|
||||
For the duration of the 'with' block, pushes a prefix onto the stack.
|
||||
Within that block, all relevant method calls (esp. to path()) will
|
||||
prefix paths with the entire prefix stack. Source and destination
|
||||
prefixes can be different, though if only one is provided they are
|
||||
both equal. To specify a no-op, use an empty string, not None.
|
||||
|
||||
Also supports the older (pre-Python-2.5) syntax:
|
||||
|
||||
if self.prefix(...args as described...):
|
||||
self.path(...)
|
||||
self.end_prefix(...)
|
||||
|
||||
Before the arrival of the 'with' statement, one was required to code
|
||||
self.prefix() and self.end_prefix() in matching pairs to push and to
|
||||
pop the prefix stacks, respectively. The older prefix() method
|
||||
returned True specifically so that the caller could indent the
|
||||
relevant block of code with 'if', just for aesthetic purposes.
|
||||
"""
|
||||
if dst is None:
|
||||
dst = src
|
||||
if build is None:
|
||||
|
|
@ -382,7 +408,57 @@ class LLManifest(object):
|
|||
self.artwork_prefix.append(src)
|
||||
self.build_prefix.append(build)
|
||||
self.dst_prefix.append(dst)
|
||||
return True # so that you can wrap it in an if to get indentation
|
||||
|
||||
# The above code is unchanged from the original implementation. What's
|
||||
# new is the return value. We're going to return an instance of
|
||||
# PrefixManager that binds this LLManifest instance and Does The Right
|
||||
# Thing on exit.
|
||||
return self.PrefixManager(self)
|
||||
|
||||
class PrefixManager(object):
|
||||
def __init__(self, manifest):
|
||||
self.manifest = manifest
|
||||
# stack attributes we manage in this LLManifest (sub)class
|
||||
# instance
|
||||
stacks = ("src_prefix", "artwork_prefix", "build_prefix", "dst_prefix")
|
||||
# If the caller wrote:
|
||||
# with self.prefix(...):
|
||||
# as intended, then bind the state of each prefix stack as it was
|
||||
# just BEFORE the call to prefix(). Since prefix() appended an
|
||||
# entry to each prefix stack, capture len()-1.
|
||||
self.prevlen = { stack: len(getattr(self.manifest, stack)) - 1
|
||||
for stack in stacks }
|
||||
|
||||
def __nonzero__(self):
|
||||
# If the caller wrote:
|
||||
# if self.prefix(...):
|
||||
# then a value of this class had better evaluate as 'True'.
|
||||
return True
|
||||
|
||||
def __enter__(self):
|
||||
# nobody uses 'with self.prefix(...) as variable:'
|
||||
return None
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
# First, if the 'with' block raised an exception, just propagate.
|
||||
# Do NOT swallow it.
|
||||
if type is not None:
|
||||
return False
|
||||
|
||||
# Okay, 'with' block completed successfully. Restore previous
|
||||
# state of each of the prefix stacks in self.stacks.
|
||||
# Note that we do NOT simply call pop() on them as end_prefix()
|
||||
# does. This is to cope with the possibility that the coder
|
||||
# changed 'if self.prefix(...):' to 'with self.prefix(...):' yet
|
||||
# forgot to remove the self.end_prefix(...) call at the bottom of
|
||||
# the block. In that case, calling pop() again would be Bad! But
|
||||
# if we restore the length of each stack to what it was before the
|
||||
# current prefix() block, it doesn't matter whether end_prefix()
|
||||
# was called or not.
|
||||
for stack, prevlen in self.prevlen.items():
|
||||
# find the attribute in 'self.manifest' named by 'stack', and
|
||||
# truncate that list back to 'prevlen'
|
||||
del getattr(self.manifest, stack)[prevlen:]
|
||||
|
||||
def end_prefix(self, descr=None):
|
||||
"""Pops a prefix off the stack. If given an argument, checks
|
||||
|
|
@ -446,29 +522,17 @@ class LLManifest(object):
|
|||
return path
|
||||
|
||||
def run_command(self, command):
|
||||
""" Runs an external command, and returns the output. Raises
|
||||
an exception if the command returns a nonzero status code. For
|
||||
debugging/informational purposes, prints out the command's
|
||||
output as it is received."""
|
||||
"""
|
||||
Runs an external command.
|
||||
Raises ManifestError exception if the command returns a nonzero status.
|
||||
"""
|
||||
print "Running command:", command
|
||||
sys.stdout.flush()
|
||||
child = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||||
shell=True)
|
||||
lines = []
|
||||
while True:
|
||||
lines.append(child.stdout.readline())
|
||||
if lines[-1] == '':
|
||||
break
|
||||
else:
|
||||
print lines[-1],
|
||||
output = ''.join(lines)
|
||||
child.stdout.close()
|
||||
status = child.wait()
|
||||
if status:
|
||||
raise ManifestError(
|
||||
"Command %s returned non-zero status (%s) \noutput:\n%s"
|
||||
% (command, status, output) )
|
||||
return output
|
||||
try:
|
||||
subprocess.check_call(command)
|
||||
except subprocess.CalledProcessError as err:
|
||||
raise ManifestError( "Command %s returned non-zero status (%s)"
|
||||
% (command, err.returncode) )
|
||||
|
||||
def created_path(self, path):
|
||||
""" Declare that you've created a path in order to
|
||||
|
|
@ -481,6 +545,7 @@ class LLManifest(object):
|
|||
def put_in_file(self, contents, dst, src=None):
|
||||
# write contents as dst
|
||||
dst_path = self.dst_path_of(dst)
|
||||
self.cmakedirs(os.path.dirname(dst_path))
|
||||
f = open(dst_path, "wb")
|
||||
try:
|
||||
f.write(contents)
|
||||
|
|
@ -618,7 +683,7 @@ class LLManifest(object):
|
|||
if self.includes(src, dst):
|
||||
try:
|
||||
os.unlink(dst)
|
||||
except OSError, err:
|
||||
except OSError as err:
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
|
|
@ -639,7 +704,7 @@ class LLManifest(object):
|
|||
dstname = os.path.join(dst, name)
|
||||
try:
|
||||
self.ccopymumble(srcname, dstname)
|
||||
except (IOError, os.error), why:
|
||||
except (IOError, os.error) as why:
|
||||
errors.append((srcname, dstname, why))
|
||||
if errors:
|
||||
raise ManifestError, errors
|
||||
|
|
|
|||
|
|
@ -2125,6 +2125,3 @@ LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BO
|
|||
target->addPendingMorphMask();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -265,4 +265,3 @@ LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIn
|
|||
{
|
||||
return getInstance()->getTexture(index)->mWearableType;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ include(Boost)
|
|||
include(LLSharedLibs)
|
||||
include(JsonCpp)
|
||||
include(GoogleBreakpad)
|
||||
include(GooglePerfTools)
|
||||
include(Copy3rdPartyLibs)
|
||||
include(ZLIB)
|
||||
include(URIPARSER)
|
||||
|
|
@ -227,6 +226,7 @@ set(llcommon_HEADER_FILES
|
|||
llstring.h
|
||||
llstringtable.h
|
||||
llstaticstringtable.h
|
||||
llstatsaccumulator.h
|
||||
llsys.h
|
||||
llthread.h
|
||||
llthreadlocalstorage.h
|
||||
|
|
@ -259,13 +259,13 @@ list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
|
|||
|
||||
if(LLCOMMON_LINK_SHARED)
|
||||
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
|
||||
if(NOT WORD_SIZE EQUAL 32)
|
||||
if(NOT ADDRESS_SIZE EQUAL 32)
|
||||
if(WINDOWS)
|
||||
add_definitions(/FIXED:NO)
|
||||
##add_definitions(/FIXED:NO)
|
||||
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
|
||||
add_definitions(-fPIC)
|
||||
endif(WINDOWS)
|
||||
endif(NOT WORD_SIZE EQUAL 32)
|
||||
endif(NOT ADDRESS_SIZE EQUAL 32)
|
||||
if(WINDOWS)
|
||||
# always generate llcommon.pdb, even for "Release" builds
|
||||
set_target_properties(llcommon PROPERTIES LINK_FLAGS "/DEBUG")
|
||||
|
|
@ -351,8 +351,4 @@ if (LL_TESTS)
|
|||
## throwing and catching exceptions.
|
||||
##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
|
||||
|
||||
# *TODO - reenable these once tcmalloc libs no longer break the build.
|
||||
#ADD_BUILD_TEST(llallocator llcommon)
|
||||
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
|
||||
#ADD_BUILD_TEST(llmemtype llcommon)
|
||||
endif (LL_TESTS)
|
||||
|
|
|
|||
|
|
@ -27,47 +27,6 @@
|
|||
#include "linden_common.h"
|
||||
#include "llallocator.h"
|
||||
|
||||
#if (LL_USE_TCMALLOC && LL_USE_HEAP_PROFILER)
|
||||
|
||||
#include "google/heap-profiler.h"
|
||||
#include "google/commandlineflags_public.h"
|
||||
|
||||
DECLARE_bool(heap_profile_use_stack_trace);
|
||||
//DECLARE_double(tcmalloc_release_rate);
|
||||
|
||||
void LLAllocator::setProfilingEnabled(bool should_enable)
|
||||
{
|
||||
// NULL disables dumping to disk
|
||||
static char const * const PREFIX = NULL;
|
||||
if(should_enable)
|
||||
{
|
||||
HeapProfilerSetUseStackTrace(false);
|
||||
HeapProfilerStart(PREFIX);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapProfilerStop();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAllocator::isProfiling()
|
||||
{
|
||||
return IsHeapProfilerRunning();
|
||||
}
|
||||
|
||||
std::string LLAllocator::getRawProfile()
|
||||
{
|
||||
// *TODO - fix google-perftools to accept an buffer to avoid this
|
||||
// malloc-copy-free cycle.
|
||||
char * buffer = GetHeapProfile();
|
||||
std::string ret = buffer;
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // LL_USE_TCMALLOC
|
||||
|
||||
//
|
||||
// stub implementations for when tcmalloc is disabled
|
||||
//
|
||||
|
|
@ -87,8 +46,6 @@ std::string LLAllocator::getRawProfile()
|
|||
return std::string();
|
||||
}
|
||||
|
||||
#endif // LL_USE_TCMALLOC
|
||||
|
||||
LLAllocatorHeapProfile const & LLAllocator::getProfile()
|
||||
{
|
||||
mProf.mLines.clear();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
|
|||
//static
|
||||
void LLCommon::initClass()
|
||||
{
|
||||
LLMemory::initClass();
|
||||
if (!sAprInitialized)
|
||||
{
|
||||
ll_init_apr();
|
||||
|
|
@ -70,5 +69,4 @@ void LLCommon::cleanupClass()
|
|||
ll_cleanup_apr();
|
||||
sAprInitialized = FALSE;
|
||||
}
|
||||
SUBSYSTEM_CLEANUP(LLMemory);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,11 @@ LLCoros::LLCoros():
|
|||
// Previously we used
|
||||
// boost::context::guarded_stack_allocator::default_stacksize();
|
||||
// empirically this is 64KB on Windows and Linux. Try quadrupling.
|
||||
#if ADDRESS_SIZE == 64
|
||||
mStackSize(512*1024)
|
||||
#else
|
||||
mStackSize(256*1024)
|
||||
#endif
|
||||
{
|
||||
// Register our cleanup() method for "mainloop" ticks
|
||||
LLEventPumps::instance().obtain("mainloop").listen(
|
||||
|
|
|
|||
|
|
@ -124,8 +124,8 @@ public:
|
|||
virtual std::string describe(bool full=true) const;
|
||||
|
||||
protected:
|
||||
typedef std::vector< std::pair<int, int> > EdgeList;
|
||||
typedef std::vector<int> VertexList;
|
||||
typedef std::vector< std::pair<std::size_t, std::size_t> > EdgeList;
|
||||
typedef std::vector<std::size_t> VertexList;
|
||||
VertexList topo_sort(int vertices, const EdgeList& edges) const;
|
||||
|
||||
/**
|
||||
|
|
@ -508,7 +508,7 @@ public:
|
|||
// been explicitly added. Rely on std::map rejecting a second attempt
|
||||
// to insert the same key. Use the map's size() as the vertex number
|
||||
// to get a distinct value for each successful insertion.
|
||||
typedef std::map<KEY, int> VertexMap;
|
||||
typedef std::map<KEY, std::size_t> VertexMap;
|
||||
VertexMap vmap;
|
||||
// Nest each of these loops because !@#$%? MSVC warns us that its
|
||||
// former broken behavior has finally been fixed -- and our builds
|
||||
|
|
|
|||
|
|
@ -1055,7 +1055,15 @@ namespace LLError
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (Settings::wasDeleted() || Globals::wasDeleted())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
|
||||
s->mShouldLogCallCounter++;
|
||||
|
|
@ -1094,7 +1102,10 @@ namespace LLError
|
|||
std::ostringstream* Log::out()
|
||||
{
|
||||
LogLock lock;
|
||||
if (lock.ok())
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (lock.ok() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
|
||||
{
|
||||
Globals* g = Globals::getInstance();
|
||||
|
||||
|
|
@ -1104,41 +1115,49 @@ namespace LLError
|
|||
return &g->messageStream;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new std::ostringstream;
|
||||
}
|
||||
|
||||
|
||||
void Log::flush(std::ostringstream* out, char* message)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(strlen(out->str().c_str()) < 128)
|
||||
{
|
||||
strcpy(message, out->str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(message, out->str().c_str(), 127);
|
||||
message[127] = '\0' ;
|
||||
}
|
||||
|
||||
Globals* g = Globals::getInstance();
|
||||
if (out == &g->messageStream)
|
||||
{
|
||||
g->messageStream.clear();
|
||||
g->messageStream.str("");
|
||||
g->messageStreamInUse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete out;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (Settings::wasDeleted() || Globals::wasDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(strlen(out->str().c_str()) < 128)
|
||||
{
|
||||
strcpy(message, out->str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(message, out->str().c_str(), 127);
|
||||
message[127] = '\0' ;
|
||||
}
|
||||
|
||||
Globals* g = Globals::getInstance();
|
||||
if (out == &g->messageStream)
|
||||
{
|
||||
g->messageStream.clear();
|
||||
g->messageStream.str("");
|
||||
g->messageStreamInUse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete out;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
void Log::flush(std::ostringstream* out, const CallSite& site)
|
||||
{
|
||||
|
|
@ -1147,7 +1166,15 @@ namespace LLError
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (Settings::wasDeleted() || Globals::wasDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Globals* g = Globals::getInstance();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
|
||||
|
|
|
|||
|
|
@ -47,13 +47,13 @@
|
|||
// namespace) that a global 'nil' macro breaks badly.
|
||||
#if defined(nil)
|
||||
// Capture the value of the macro 'nil', hoping int is an appropriate type.
|
||||
static const int nil_(nil);
|
||||
static const auto nil_(nil);
|
||||
// Now forget the macro.
|
||||
#undef nil
|
||||
// Finally, reintroduce 'nil' as a properly-scoped alias for the previously-
|
||||
// defined const 'nil_'. Make it static since otherwise it produces duplicate-
|
||||
// symbol link errors later.
|
||||
static const int& nil(nil_);
|
||||
static const auto& nil(nil_);
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
|
|
|||
|
|
@ -281,7 +281,8 @@ const std::string LLEventPump::ANONYMOUS = std::string();
|
|||
|
||||
LLEventPump::LLEventPump(const std::string& name, bool tweak):
|
||||
// Register every new instance with LLEventPumps
|
||||
mName(LLEventPumps::instance().registerNew(*this, name, tweak)),
|
||||
mRegistry(LLEventPumps::instance().getHandle()),
|
||||
mName(mRegistry.get()->registerNew(*this, name, tweak)),
|
||||
mSignal(new LLStandardSignal()),
|
||||
mEnabled(true)
|
||||
{}
|
||||
|
|
@ -292,8 +293,13 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):
|
|||
|
||||
LLEventPump::~LLEventPump()
|
||||
{
|
||||
// Unregister this doomed instance from LLEventPumps
|
||||
LLEventPumps::instance().unregister(*this);
|
||||
// Unregister this doomed instance from LLEventPumps -- but only if
|
||||
// LLEventPumps is still around!
|
||||
LLEventPumps* registry = mRegistry.get();
|
||||
if (registry)
|
||||
{
|
||||
registry->unregister(*this);
|
||||
}
|
||||
}
|
||||
|
||||
// static data member
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
#include "lldependencies.h"
|
||||
#include "llstl.h"
|
||||
#include "llexception.h"
|
||||
#include "llhandle.h"
|
||||
|
||||
/*==========================================================================*|
|
||||
// override this to allow binding free functions with more parameters
|
||||
|
|
@ -227,7 +228,15 @@ class LLEventPump;
|
|||
* LLEventPumps is a Singleton manager through which one typically accesses
|
||||
* this subsystem.
|
||||
*/
|
||||
class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
|
||||
// LLEventPumps isa LLHandleProvider only for (hopefully rare) long-lived
|
||||
// class objects that must refer to this class late in their lifespan, say in
|
||||
// the destructor. Specifically, the case that matters is a possible reference
|
||||
// after LLEventPumps::deleteSingleton(). (Lingering LLEventPump instances are
|
||||
// capable of this.) In that case, instead of calling LLEventPumps::instance()
|
||||
// again -- resurrecting the deleted LLSingleton -- store an
|
||||
// LLHandle<LLEventPumps> and test it before use.
|
||||
class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>,
|
||||
public LLHandleProvider<LLEventPumps>
|
||||
{
|
||||
LLSINGLETON(LLEventPumps);
|
||||
public:
|
||||
|
|
@ -590,6 +599,9 @@ private:
|
|||
return this->listen_impl(name, listener, after, before);
|
||||
}
|
||||
|
||||
// must precede mName; see LLEventPump::LLEventPump()
|
||||
LLHandle<LLEventPumps> mRegistry;
|
||||
|
||||
std::string mName;
|
||||
|
||||
protected:
|
||||
|
|
@ -817,14 +829,14 @@ public:
|
|||
mConnection(new LLBoundListener)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Copy constructor. Copy shared_ptrs to original instance data.
|
||||
LLListenerWrapperBase(const LLListenerWrapperBase& that):
|
||||
mName(that.mName),
|
||||
mConnection(that.mConnection)
|
||||
{
|
||||
}
|
||||
virtual ~LLListenerWrapperBase() {}
|
||||
virtual ~LLListenerWrapperBase() {}
|
||||
|
||||
/// Ask LLEventPump::listen() for the listener name
|
||||
virtual void accept_name(const std::string& name) const
|
||||
|
|
|
|||
|
|
@ -90,33 +90,15 @@ public:
|
|||
#if LL_FASTTIMER_USE_RDTSC
|
||||
static U32 getCPUClockCount32()
|
||||
{
|
||||
U32 ret_val;
|
||||
__asm
|
||||
{
|
||||
_emit 0x0f
|
||||
_emit 0x31
|
||||
shr eax,8
|
||||
shl edx,24
|
||||
or eax, edx
|
||||
mov dword ptr [ret_val], eax
|
||||
}
|
||||
return ret_val;
|
||||
unsigned __int64 val = __rdtsc();
|
||||
val = val >> 8;
|
||||
return static_cast<U32>(val);
|
||||
}
|
||||
|
||||
// return full timer value, *not* shifted by 8 bits
|
||||
static U64 getCPUClockCount64()
|
||||
{
|
||||
U64 ret_val;
|
||||
__asm
|
||||
{
|
||||
_emit 0x0f
|
||||
_emit 0x31
|
||||
mov eax,eax
|
||||
mov edx,edx
|
||||
mov dword ptr [ret_val+4], edx
|
||||
mov dword ptr [ret_val], eax
|
||||
}
|
||||
return ret_val;
|
||||
return static_cast<U64>( __rdtsc() );
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -173,16 +155,16 @@ public:
|
|||
// Mac+Linux+Solaris FAST x86 implementation of CPU clock
|
||||
static U32 getCPUClockCount32()
|
||||
{
|
||||
U64 x;
|
||||
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
|
||||
return (U32)(x >> 8);
|
||||
U32 low(0),high(0);
|
||||
__asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
|
||||
return (low>>8) | (high<<24);
|
||||
}
|
||||
|
||||
static U64 getCPUClockCount64()
|
||||
{
|
||||
U64 x;
|
||||
__asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
|
||||
return x;
|
||||
U32 low(0),high(0);
|
||||
__asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
|
||||
return (U64)low | ( ((U64)high) << 32);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -182,7 +182,14 @@ int LLFile::mkdir(const std::string& dirname, int perms)
|
|||
int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
|
||||
#endif
|
||||
// We often use mkdir() to ensure the existence of a directory that might
|
||||
// already exist. Don't spam the log if it does.
|
||||
// already exist. There is no known case in which we want to call out as
|
||||
// an error the requested directory already existing.
|
||||
if (rc < 0 && errno == EEXIST)
|
||||
{
|
||||
// this is not the error you want, move along
|
||||
return 0;
|
||||
}
|
||||
// anything else might be a problem
|
||||
return warnif("mkdir", dirname, rc, EEXIST);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ typedef FILE LLFILE;
|
|||
typedef struct _stat llstat;
|
||||
#else
|
||||
typedef struct stat llstat;
|
||||
#include <bits/postypes.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
|
|
@ -69,6 +69,7 @@ public:
|
|||
|
||||
// perms is a permissions mask like 0777 or 0700. In most cases it will
|
||||
// be overridden by the user's umask. It is ignored on Windows.
|
||||
// mkdir() considers "directory already exists" to be SUCCESS.
|
||||
static int mkdir(const std::string& filename, int perms = 0700);
|
||||
|
||||
static int rmdir(const std::string& filename);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define LLHANDLE_H
|
||||
|
||||
#include "llpointer.h"
|
||||
#include "llrefcount.h"
|
||||
#include "llexception.h"
|
||||
#include <stdexcept>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ private:
|
|||
// not always equal &typeid(A) in some other part. Use special comparator.
|
||||
struct type_info_ptr_comp
|
||||
{
|
||||
bool operator()(const std::type_info* lhs, const std::type_info* rhs)
|
||||
bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
|
||||
{
|
||||
return lhs->before(*rhs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,31 @@
|
|||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
// As of 2017-05-06, as far as nat knows, only clang supports __has_feature().
|
||||
// Unfortunately VS2013's preprocessor shortcut logic doesn't prevent it from
|
||||
// producing (fatal) warnings for defined(__clang__) && __has_feature(...).
|
||||
// Have to work around that.
|
||||
#if ! defined(__clang__)
|
||||
#define __has_feature(x) 0
|
||||
#endif // __clang__
|
||||
|
||||
#if defined(LL_TEST_llinstancetracker) && __has_feature(cxx_noexcept)
|
||||
// ~LLInstanceTracker() performs llassert_always() validation. That's fine in
|
||||
// production code, since the llassert_always() is implemented as an LL_ERRS
|
||||
// message, which will crash-with-message. In our integration test executable,
|
||||
// though, this llassert_always() throws an exception instead so we can test
|
||||
// error conditions and continue running the test. However -- as of C++11,
|
||||
// destructors are implicitly noexcept(true). Unless we mark
|
||||
// ~LLInstanceTracker() noexcept(false), the test executable crashes even on
|
||||
// the ATTEMPT to throw.
|
||||
#define LLINSTANCETRACKER_DTOR_NOEXCEPT noexcept(false)
|
||||
#else
|
||||
// If we're building for production, or in fact building *any other* test, or
|
||||
// we're using a compiler that doesn't support __has_feature(), or we're not
|
||||
// compiling with a C++ version that supports noexcept -- don't specify it.
|
||||
#define LLINSTANCETRACKER_DTOR_NOEXCEPT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Base class manages "class-static" data that must actually have singleton
|
||||
* semantics: one instance per process, rather than one instance per module as
|
||||
|
|
@ -198,11 +223,11 @@ protected:
|
|||
getStatic();
|
||||
add_(key);
|
||||
}
|
||||
virtual ~LLInstanceTracker()
|
||||
virtual ~LLInstanceTracker() LLINSTANCETRACKER_DTOR_NOEXCEPT
|
||||
{
|
||||
// it's unsafe to delete instances of this type while all instances are being iterated over.
|
||||
llassert_always(getStatic().getDepth() == 0);
|
||||
remove_();
|
||||
remove_();
|
||||
}
|
||||
virtual void setKey(KEY key) { remove_(); add_(key); }
|
||||
virtual const KEY& getKey() const { return mInstanceKey; }
|
||||
|
|
@ -335,7 +360,7 @@ protected:
|
|||
getStatic();
|
||||
getSet_().insert(static_cast<T*>(this));
|
||||
}
|
||||
virtual ~LLInstanceTracker()
|
||||
virtual ~LLInstanceTracker() LLINSTANCETRACKER_DTOR_NOEXCEPT
|
||||
{
|
||||
// it's unsafe to delete instances of this type while all instances are being iterated over.
|
||||
llassert_always(getStatic().getDepth() == 0);
|
||||
|
|
|
|||
|
|
@ -12,12 +12,10 @@
|
|||
*
|
||||
* also relevant:
|
||||
*
|
||||
* Template parameter deduction for constructors
|
||||
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0091r0.html
|
||||
*
|
||||
* https://github.com/viboes/std-make
|
||||
*
|
||||
* but obviously we're not there yet.
|
||||
* Template argument deduction for class templates
|
||||
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html
|
||||
* was apparently adopted in June 2016? Unclear when compilers will
|
||||
* portably support this, but there is hope.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2015&license=viewerlgpl$
|
||||
* Copyright (c) 2015, Linden Research, Inc.
|
||||
|
|
|
|||
|
|
@ -44,10 +44,10 @@
|
|||
#include "llsys.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lltrace.h"
|
||||
#include "llerror.h"
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//static
|
||||
char* LLMemory::reserveMem = 0;
|
||||
U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
|
||||
U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
|
||||
static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
|
||||
|
|
@ -78,29 +78,6 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
|
|||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::initClass()
|
||||
{
|
||||
if (!reserveMem)
|
||||
{
|
||||
reserveMem = new char[16*1024]; // reserve 16K for out of memory error handling
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::cleanupClass()
|
||||
{
|
||||
delete [] reserveMem;
|
||||
reserveMem = NULL;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::freeReserve()
|
||||
{
|
||||
delete [] reserveMem;
|
||||
reserveMem = NULL;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
|
||||
{
|
||||
|
|
@ -111,19 +88,18 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_f
|
|||
//static
|
||||
void LLMemory::updateMemoryInfo()
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
HANDLE self = GetCurrentProcess();
|
||||
#if LL_WINDOWS
|
||||
PROCESS_MEMORY_COUNTERS counters;
|
||||
|
||||
if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
|
||||
|
||||
if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
|
||||
{
|
||||
LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
|
||||
return ;
|
||||
}
|
||||
|
||||
sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
|
||||
sAllocatedMemInKB = U64Bytes(counters.WorkingSetSize) ;
|
||||
sample(sAllocatedMem, sAllocatedMemInKB);
|
||||
sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
|
||||
sAllocatedPageSizeInKB = U64Bytes(counters.PagefileUsage) ;
|
||||
sample(sVirtualMem, sAllocatedPageSizeInKB);
|
||||
|
||||
U32Kilobytes avail_phys, avail_virtual;
|
||||
|
|
@ -140,9 +116,9 @@ void LLMemory::updateMemoryInfo()
|
|||
}
|
||||
#else
|
||||
//not valid for other systems for now.
|
||||
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
|
||||
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
|
||||
sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
|
||||
sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
|
||||
#endif
|
||||
|
||||
return ;
|
||||
|
|
@ -169,7 +145,7 @@ void* LLMemory::tryToAlloc(void* address, U32 size)
|
|||
return address ;
|
||||
#else
|
||||
return (void*)0x01 ; //skip checking
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -183,7 +159,7 @@ void LLMemory::logMemoryInfo(BOOL update)
|
|||
|
||||
LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
|
||||
LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
|
||||
LL_INFOS() << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
|
||||
LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
|
||||
LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
|
||||
|
||||
LL_INFOS() << "--- private pool information -- " << LL_ENDL ;
|
||||
|
|
@ -263,12 +239,12 @@ U32Kilobytes LLMemory::getAllocatedMemKB()
|
|||
|
||||
#if defined(LL_WINDOWS)
|
||||
|
||||
//static
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
HANDLE self = GetCurrentProcess();
|
||||
PROCESS_MEMORY_COUNTERS counters;
|
||||
|
||||
if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
|
||||
|
||||
if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
|
||||
{
|
||||
LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
|
||||
return 0;
|
||||
|
|
@ -277,35 +253,8 @@ U64 LLMemory::getCurrentRSS()
|
|||
return counters.WorkingSetSize;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
PROCESS_MEMORY_COUNTERS pmc ;
|
||||
U32 ret = 0 ;
|
||||
|
||||
if (GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) )
|
||||
{
|
||||
ret = pmc.WorkingSetSize ;
|
||||
}
|
||||
|
||||
return ret ;
|
||||
}
|
||||
|
||||
#elif defined(LL_DARWIN)
|
||||
|
||||
/*
|
||||
The API used here is not capable of dealing with 64-bit memory sizes, but is available before 10.4.
|
||||
|
||||
Once we start requiring 10.4, we can use the updated API, which looks like this:
|
||||
|
||||
task_basic_info_64_data_t basicInfo;
|
||||
mach_msg_type_number_t basicInfoCount = TASK_BASIC_INFO_64_COUNT;
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
|
||||
|
||||
Of course, this doesn't gain us anything unless we start building the viewer as a 64-bit executable, since that's the only way
|
||||
for our memory allocation to exceed 2^32.
|
||||
*/
|
||||
|
||||
// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
|
||||
// {
|
||||
// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
|
||||
|
|
@ -318,16 +267,15 @@ U32 LLMemory::getWorkingSetSize()
|
|||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
U64 residentSize = 0;
|
||||
task_basic_info_data_t basicInfo;
|
||||
mach_msg_type_number_t basicInfoCount = TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
|
||||
mach_task_basic_info_data_t basicInfo;
|
||||
mach_msg_type_number_t basicInfoCount = MACH_TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&basicInfo, &basicInfoCount) == KERN_SUCCESS)
|
||||
{
|
||||
residentSize = basicInfo.resident_size;
|
||||
|
||||
// If we ever wanted it, the process virtual size is also available as:
|
||||
// virtualSize = basicInfo.virtual_size;
|
||||
|
||||
// LL_INFOS() << "resident size is " << residentSize << LL_ENDL;
|
||||
// residentSize = basicInfo.resident_size;
|
||||
// Although this method is defined to return the "resident set size,"
|
||||
// in fact what callers want from it is the total virtual memory
|
||||
// consumed by the application.
|
||||
residentSize = basicInfo.virtual_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -337,11 +285,6 @@ U64 LLMemory::getCurrentRSS()
|
|||
return residentSize;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#elif defined(LL_LINUX)
|
||||
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
|
|
@ -353,7 +296,7 @@ U64 LLMemory::getCurrentRSS()
|
|||
if (fp == NULL)
|
||||
{
|
||||
LL_WARNS() << "couldn't open " << statPath << LL_ENDL;
|
||||
goto bail;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Eee-yew! See Documentation/filesystems/proc.txt in your
|
||||
|
|
@ -372,15 +315,9 @@ U64 LLMemory::getCurrentRSS()
|
|||
|
||||
fclose(fp);
|
||||
|
||||
bail:
|
||||
return rss;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#elif LL_SOLARIS
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -410,11 +347,6 @@ U64 LLMemory::getCurrentRSS()
|
|||
return((U64)proc_psinfo.pr_rssize * 1024);
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
|
|
@ -422,11 +354,6 @@ U64 LLMemory::getCurrentRSS()
|
|||
return 0;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
|
@ -591,7 +518,7 @@ char* LLPrivateMemoryPool::LLMemoryBlock::allocate()
|
|||
void LLPrivateMemoryPool::LLMemoryBlock::freeMem(void* addr)
|
||||
{
|
||||
//bit index
|
||||
U32 idx = ((U32)addr - (U32)mBuffer - mDummySize) / mSlotSize ;
|
||||
uintptr_t idx = ((uintptr_t)addr - (uintptr_t)mBuffer - mDummySize) / mSlotSize ;
|
||||
|
||||
U32* bits = &mUsageBits ;
|
||||
if(idx >= 32)
|
||||
|
|
@ -773,7 +700,7 @@ char* LLPrivateMemoryPool::LLMemoryChunk::allocate(U32 size)
|
|||
|
||||
void LLPrivateMemoryPool::LLMemoryChunk::freeMem(void* addr)
|
||||
{
|
||||
U32 blk_idx = getPageIndex((U32)addr) ;
|
||||
U32 blk_idx = getPageIndex((uintptr_t)addr) ;
|
||||
LLMemoryBlock* blk = (LLMemoryBlock*)(mMetaBuffer + blk_idx * sizeof(LLMemoryBlock)) ;
|
||||
blk = blk->mSelf ;
|
||||
|
||||
|
|
@ -798,7 +725,7 @@ bool LLPrivateMemoryPool::LLMemoryChunk::empty()
|
|||
|
||||
bool LLPrivateMemoryPool::LLMemoryChunk::containsAddress(const char* addr) const
|
||||
{
|
||||
return (U32)mBuffer <= (U32)addr && (U32)mBuffer + mBufferSize > (U32)addr ;
|
||||
return (uintptr_t)mBuffer <= (uintptr_t)addr && (uintptr_t)mBuffer + mBufferSize > (uintptr_t)addr ;
|
||||
}
|
||||
|
||||
//debug use
|
||||
|
|
@ -831,13 +758,13 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
|
|||
for(U32 i = 1 ; i < blk_list.size(); i++)
|
||||
{
|
||||
total_size += blk_list[i]->getBufferSize() ;
|
||||
if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
|
||||
if((uintptr_t)blk_list[i]->getBuffer() < (uintptr_t)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
|
||||
{
|
||||
LL_ERRS() << "buffer corrupted." << LL_ENDL ;
|
||||
}
|
||||
}
|
||||
|
||||
llassert_always(total_size + mMinBlockSize >= mBufferSize - ((U32)mDataBuffer - (U32)mBuffer)) ;
|
||||
llassert_always(total_size + mMinBlockSize >= mBufferSize - ((uintptr_t)mDataBuffer - (uintptr_t)mBuffer)) ;
|
||||
|
||||
U32 blk_num = (mBufferSize - (mDataBuffer - mBuffer)) / mMinBlockSize ;
|
||||
for(U32 i = 0 ; i < blk_num ; )
|
||||
|
|
@ -860,7 +787,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
|
|||
#endif
|
||||
#if 0
|
||||
LL_INFOS() << "---------------------------" << LL_ENDL ;
|
||||
LL_INFOS() << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
|
||||
LL_INFOS() << "Chunk buffer: " << (uintptr_t)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
|
||||
|
||||
LL_INFOS() << "available blocks ... " << LL_ENDL ;
|
||||
for(S32 i = 0 ; i < mBlockLevels ; i++)
|
||||
|
|
@ -868,7 +795,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
|
|||
LLMemoryBlock* blk = mAvailBlockList[i] ;
|
||||
while(blk)
|
||||
{
|
||||
LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
|
||||
LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
|
||||
blk = blk->mNext ;
|
||||
}
|
||||
}
|
||||
|
|
@ -879,7 +806,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
|
|||
LLMemoryBlock* blk = mFreeSpaceList[i] ;
|
||||
while(blk)
|
||||
{
|
||||
LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
|
||||
LL_INFOS() << "blk buffer " << (uintptr_t)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
|
||||
blk = blk->mNext ;
|
||||
}
|
||||
}
|
||||
|
|
@ -1155,9 +1082,9 @@ void LLPrivateMemoryPool::LLMemoryChunk::addToAvailBlockList(LLMemoryBlock* blk)
|
|||
return ;
|
||||
}
|
||||
|
||||
U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(U32 addr)
|
||||
U32 LLPrivateMemoryPool::LLMemoryChunk::getPageIndex(uintptr_t addr)
|
||||
{
|
||||
return (addr - (U32)mDataBuffer) / mMinBlockSize ;
|
||||
return (addr - (uintptr_t)mDataBuffer) / mMinBlockSize ;
|
||||
}
|
||||
|
||||
//for mAvailBlockList
|
||||
|
|
@ -1495,7 +1422,7 @@ void LLPrivateMemoryPool::removeChunk(LLMemoryChunk* chunk)
|
|||
|
||||
U16 LLPrivateMemoryPool::findHashKey(const char* addr)
|
||||
{
|
||||
return (((U32)addr) / CHUNK_SIZE) % mHashFactor ;
|
||||
return (((uintptr_t)addr) / CHUNK_SIZE) % mHashFactor ;
|
||||
}
|
||||
|
||||
LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* addr)
|
||||
|
|
@ -1720,7 +1647,7 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
|
|||
S32 k = 0 ;
|
||||
for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter)
|
||||
{
|
||||
LL_INFOS() << k++ << ", " << (U32)iter->first << " : " << iter->second << LL_ENDL ;
|
||||
LL_INFOS() << k++ << ", " << (uintptr_t)iter->first << " : " << iter->second << LL_ENDL ;
|
||||
}
|
||||
sMemAllocationTracker.clear() ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
|
|||
//------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
#if !LL_USE_TCMALLOC
|
||||
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
|
||||
{
|
||||
#if defined(LL_WINDOWS)
|
||||
|
|
@ -187,13 +186,6 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r
|
|||
#endif
|
||||
}
|
||||
|
||||
#else // USE_TCMALLOC
|
||||
// ll_aligned_foo_16 are not needed with tcmalloc
|
||||
#define ll_aligned_malloc_16 malloc
|
||||
#define ll_aligned_realloc_16(a,b,c) realloc(a,b)
|
||||
#define ll_aligned_free_16 free
|
||||
#endif // USE_TCMALLOC
|
||||
|
||||
inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32().
|
||||
{
|
||||
#if defined(LL_WINDOWS)
|
||||
|
|
@ -342,13 +334,9 @@ inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __
|
|||
class LL_COMMON_API LLMemory
|
||||
{
|
||||
public:
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
static void freeReserve();
|
||||
// Return the resident set size of the current process, in bytes.
|
||||
// Return value is zero if not known.
|
||||
static U64 getCurrentRSS();
|
||||
static U32 getWorkingSetSize();
|
||||
static void* tryToAlloc(void* address, U32 size);
|
||||
static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
|
||||
static void updateMemoryInfo() ;
|
||||
|
|
@ -359,7 +347,6 @@ public:
|
|||
static U32Kilobytes getMaxMemKB() ;
|
||||
static U32Kilobytes getAllocatedMemKB() ;
|
||||
private:
|
||||
static char* reserveMem;
|
||||
static U32Kilobytes sAvailPhysicalMemInKB ;
|
||||
static U32Kilobytes sMaxPhysicalMemInKB ;
|
||||
static U32Kilobytes sAllocatedMemInKB;
|
||||
|
|
@ -423,7 +410,7 @@ public:
|
|||
{
|
||||
bool operator()(const LLMemoryBlock* const& lhs, const LLMemoryBlock* const& rhs)
|
||||
{
|
||||
return (U32)lhs->getBuffer() < (U32)rhs->getBuffer();
|
||||
return (uintptr_t)lhs->getBuffer() < (uintptr_t)rhs->getBuffer();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -454,7 +441,7 @@ public:
|
|||
void dump() ;
|
||||
|
||||
private:
|
||||
U32 getPageIndex(U32 addr) ;
|
||||
U32 getPageIndex(uintptr_t addr) ;
|
||||
U32 getBlockLevel(U32 size) ;
|
||||
U16 getPageLevel(U32 size) ;
|
||||
LLMemoryBlock* addBlock(U32 blk_idx) ;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@
|
|||
#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
|
||||
#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
|
||||
//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
|
||||
|
||||
#if ADDRESS_SIZE == 64
|
||||
// That one is all over the place for x64 builds.
|
||||
#pragma warning( disable : 4267 ) // 'var' : conversion from 'size_t' to 'type', possible loss of data)
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
|
||||
#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
|
||||
#pragma warning( disable : 4996 ) // warning: deprecated
|
||||
|
|
@ -186,13 +192,9 @@
|
|||
# define LL_COMMON_API
|
||||
#endif // LL_COMMON_LINK_SHARED
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define LL_TYPEOF(exp) decltype(exp)
|
||||
#elif LL_LINUX
|
||||
#define LL_TYPEOF(exp) typeof(exp)
|
||||
#elif LL_DARWIN
|
||||
#define LL_TYPEOF(exp) typeof(exp)
|
||||
#endif
|
||||
// With C++11, decltype() is standard. We no longer need a platform-dependent
|
||||
// macro to get the type of an expression.
|
||||
#define LL_TYPEOF(expr) decltype(expr)
|
||||
|
||||
#define LL_TO_STRING_HELPER(x) #x
|
||||
#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
|
||||
|
|
|
|||
|
|
@ -517,6 +517,10 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
|
|||
|
||||
LLProcess::LLProcess(const LLSDOrParams& params):
|
||||
mAutokill(params.autokill),
|
||||
// Because 'autokill' originally meant both 'autokill' and 'attached', to
|
||||
// preserve existing semantics, we promise that mAttached defaults to the
|
||||
// same setting as mAutokill.
|
||||
mAttached(params.attached.isProvided()? params.attached : params.autokill),
|
||||
mPipes(NSLOTS)
|
||||
{
|
||||
// Hmm, when you construct a ptr_vector with a size, it merely reserves
|
||||
|
|
@ -625,9 +629,9 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
// std handles and the like, and that's a bit more detachment than we
|
||||
// want. autokill=false just means not to implicitly kill the child when
|
||||
// the parent terminates!
|
||||
// chkapr(apr_procattr_detach_set(procattr, params.autokill? 0 : 1));
|
||||
// chkapr(apr_procattr_detach_set(procattr, mAutokill? 0 : 1));
|
||||
|
||||
if (params.autokill)
|
||||
if (mAutokill)
|
||||
{
|
||||
#if ! defined(APR_HAS_PROCATTR_AUTOKILL_SET)
|
||||
// Our special preprocessor symbol isn't even defined -- wrong APR
|
||||
|
|
@ -696,7 +700,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
// take steps to terminate the child. This is all suspenders-and-belt: in
|
||||
// theory our destructor should kill an autokill child, but in practice
|
||||
// that doesn't always work (e.g. VWR-21538).
|
||||
if (params.autokill)
|
||||
if (mAutokill)
|
||||
{
|
||||
/*==========================================================================*|
|
||||
// NO: There may be an APR bug, not sure -- but at least on Mac, when
|
||||
|
|
@ -799,7 +803,7 @@ LLProcess::~LLProcess()
|
|||
sProcessListener.dropPoll(*this);
|
||||
}
|
||||
|
||||
if (mAutokill)
|
||||
if (mAttached)
|
||||
{
|
||||
kill("destructor");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ public:
|
|||
args("args"),
|
||||
cwd("cwd"),
|
||||
autokill("autokill", true),
|
||||
attached("attached", true),
|
||||
files("files"),
|
||||
postend("postend"),
|
||||
desc("desc")
|
||||
|
|
@ -183,9 +184,31 @@ public:
|
|||
Multiple<std::string> args;
|
||||
/// current working directory, if need it changed
|
||||
Optional<std::string> cwd;
|
||||
/// implicitly kill process on destruction of LLProcess object
|
||||
/// (default true)
|
||||
/// implicitly kill child process on termination of parent, whether
|
||||
/// voluntary or crash (default true)
|
||||
Optional<bool> autokill;
|
||||
/// implicitly kill process on destruction of LLProcess object
|
||||
/// (default same as autokill)
|
||||
///
|
||||
/// Originally, 'autokill' conflated two concepts: kill child process on
|
||||
/// - destruction of its LLProcess object, and
|
||||
/// - termination of parent process, voluntary or otherwise.
|
||||
///
|
||||
/// It's useful to tease these apart. Some child processes are sent a
|
||||
/// "clean up and terminate" message before the associated LLProcess
|
||||
/// object is destroyed. A child process launched with attached=false
|
||||
/// has an extra time window from the destruction of its LLProcess
|
||||
/// until parent-process termination in which to perform its own
|
||||
/// orderly shutdown, yet autokill=true still guarantees that we won't
|
||||
/// accumulate orphan instances of such processes indefinitely. With
|
||||
/// attached=true, if a child process cannot clean up between the
|
||||
/// shutdown message and LLProcess destruction (presumably very soon
|
||||
/// thereafter), it's forcibly killed anyway -- which can lead to
|
||||
/// distressing user-visible crash indications.
|
||||
///
|
||||
/// (The usefulness of attached=true with autokill=false is less
|
||||
/// clear, but we don't prohibit that combination.)
|
||||
Optional<bool> attached;
|
||||
/**
|
||||
* Up to three FileParam items: for child stdin, stdout, stderr.
|
||||
* Passing two FileParam entries means default treatment for stderr,
|
||||
|
|
@ -540,7 +563,7 @@ private:
|
|||
std::string mDesc;
|
||||
std::string mPostend;
|
||||
apr_proc_t mProcess;
|
||||
bool mAutokill;
|
||||
bool mAutokill, mAttached;
|
||||
Status mStatus;
|
||||
// explicitly want this ptr_vector to be able to store NULLs
|
||||
typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
|
||||
|
|
|
|||
|
|
@ -26,9 +26,11 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llprocessor.h"
|
||||
|
||||
#include "llstring.h"
|
||||
#include "stringize.h"
|
||||
#include "llerror.h"
|
||||
|
||||
#include <iomanip>
|
||||
//#include <memory>
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
|
@ -188,7 +190,7 @@ namespace
|
|||
case 0xF: return "Intel Pentium 4";
|
||||
case 0x10: return "Intel Itanium 2 (IA-64)";
|
||||
}
|
||||
return "Unknown";
|
||||
return STRINGIZE("Intel <unknown 0x" << std::hex << composed_family << ">");
|
||||
}
|
||||
|
||||
std::string amd_CPUFamilyName(int composed_family)
|
||||
|
|
@ -201,26 +203,26 @@ namespace
|
|||
case 0xF: return "AMD K8";
|
||||
case 0x10: return "AMD K8L";
|
||||
}
|
||||
return "Unknown";
|
||||
return STRINGIZE("AMD <unknown 0x" << std::hex << composed_family << ">");
|
||||
}
|
||||
|
||||
std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family)
|
||||
{
|
||||
const char* intel_string = "GenuineIntel";
|
||||
const char* amd_string = "AuthenticAMD";
|
||||
if(!strncmp(cpu_vendor, intel_string, strlen(intel_string)))
|
||||
if (LLStringUtil::startsWith(cpu_vendor, intel_string))
|
||||
{
|
||||
U32 composed_family = family + ext_family;
|
||||
return intel_CPUFamilyName(composed_family);
|
||||
}
|
||||
else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
|
||||
else if (LLStringUtil::startsWith(cpu_vendor, amd_string))
|
||||
{
|
||||
U32 composed_family = (family == 0xF)
|
||||
? family + ext_family
|
||||
: family;
|
||||
return amd_CPUFamilyName(composed_family);
|
||||
}
|
||||
return "Unknown";
|
||||
return STRINGIZE("Unrecognized CPU vendor <" << cpu_vendor << ">");
|
||||
}
|
||||
|
||||
} // end unnamed namespace
|
||||
|
|
@ -258,8 +260,8 @@ public:
|
|||
return hasExtension("Altivec");
|
||||
}
|
||||
|
||||
std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); }
|
||||
std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); }
|
||||
std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unset family").asString(); }
|
||||
std::string getCPUBrandName() const { return getInfo(eBrandName, "Unset brand").asString(); }
|
||||
|
||||
// This is virtual to support a different linux format.
|
||||
// *NOTE:Mani - I didn't want to screw up server use of this data...
|
||||
|
|
@ -271,7 +273,7 @@ public:
|
|||
out << "//////////////////////////" << std::endl;
|
||||
out << "Processor Name: " << getCPUBrandName() << std::endl;
|
||||
out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl;
|
||||
out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl;
|
||||
out << "Vendor: " << getInfo(eVendor, "Unset vendor").asString() << std::endl;
|
||||
out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl;
|
||||
out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl;
|
||||
out << "Model: " << getInfo(eModel, 0) << std::endl;
|
||||
|
|
@ -398,7 +400,7 @@ static F64 calculate_cpu_frequency(U32 measure_msecs)
|
|||
HANDLE hThread = GetCurrentThread();
|
||||
unsigned long dwCurPriorityClass = GetPriorityClass(hProcess);
|
||||
int iCurThreadPriority = GetThreadPriority(hThread);
|
||||
unsigned long dwProcessMask, dwSystemMask, dwNewMask = 1;
|
||||
DWORD_PTR dwProcessMask, dwSystemMask, dwNewMask = 1;
|
||||
GetProcessAffinityMask(hProcess, &dwProcessMask, &dwSystemMask);
|
||||
|
||||
SetPriorityClass(hProcess, REALTIME_PRIORITY_CLASS);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,30 @@
|
|||
#define LLSAFEHANDLE_H
|
||||
|
||||
#include "llerror.h" // *TODO: consider eliminating this
|
||||
#include "llsingleton.h"
|
||||
|
||||
/*==========================================================================*|
|
||||
____ ___ _ _ ___ _____ _ _ ____ _____ _
|
||||
| _ \ / _ \ | \ | |/ _ \_ _| | | | / ___|| ____| |
|
||||
| | | | | | | | \| | | | || | | | | \___ \| _| | |
|
||||
| |_| | |_| | | |\ | |_| || | | |_| |___) | |___|_|
|
||||
|____/ \___/ |_| \_|\___/ |_| \___/|____/|_____(_)
|
||||
|
||||
This handle class is deprecated. Unfortunately it is already in widespread use
|
||||
to reference the LLObjectSelection and LLParcelSelection classes, but do not
|
||||
apply LLSafeHandle to other classes, or declare new instances.
|
||||
|
||||
Instead, use LLPointer or other smart pointer types with appropriate checks
|
||||
for NULL. If you're certain the reference cannot (or must not) be NULL,
|
||||
consider storing a C++ reference instead -- or use (e.g.) LLCheckedHandle.
|
||||
|
||||
When an LLSafeHandle<T> containing NULL is dereferenced, it resolves to a
|
||||
canonical "null" T instance. This raises issues about the lifespan of the
|
||||
"null" instance. In addition to encouraging sloppy coding practices, it
|
||||
potentially masks bugs when code that performs some mutating operation
|
||||
inadvertently applies it to the "null" instance. That result might or might
|
||||
not ever affect subsequent computations.
|
||||
|*==========================================================================*/
|
||||
|
||||
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
||||
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
||||
|
|
@ -112,10 +136,6 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Type* (*NullFunc)();
|
||||
static const NullFunc sNullFunc;
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
|
|
@ -150,9 +170,25 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
// Define an LLSingleton whose sole purpose is to hold a "null instance"
|
||||
// of the subject Type: the canonical instance to dereference if this
|
||||
// LLSafeHandle actually holds a null pointer. We use LLSingleton
|
||||
// specifically so that the "null instance" can be cleaned up at a well-
|
||||
// defined time, specifically LLSingletonBase::deleteAll().
|
||||
// Of course, as with any LLSingleton, the "null instance" is only
|
||||
// instantiated on demand -- in this case, if you actually try to
|
||||
// dereference an LLSafeHandle containing null.
|
||||
class NullInstanceHolder: public LLSingleton<NullInstanceHolder>
|
||||
{
|
||||
LLSINGLETON_EMPTY_CTOR(NullInstanceHolder);
|
||||
~NullInstanceHolder() {}
|
||||
public:
|
||||
Type mNullInstance;
|
||||
};
|
||||
|
||||
static Type* nonNull(Type* ptr)
|
||||
{
|
||||
return ptr == NULL ? sNullFunc() : ptr;
|
||||
return ptr? ptr : &NullInstanceHolder::instance().mNullInstance;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -391,62 +391,20 @@ void LLSingletonBase::deleteAll()
|
|||
}
|
||||
}
|
||||
|
||||
/*------------------------ Final cleanup management ------------------------*/
|
||||
class LLSingletonBase::MasterRefcount
|
||||
{
|
||||
public:
|
||||
// store a POD int so it will be statically initialized to 0
|
||||
int refcount;
|
||||
};
|
||||
static LLSingletonBase::MasterRefcount sMasterRefcount;
|
||||
|
||||
LLSingletonBase::ref_ptr_t LLSingletonBase::get_master_refcount()
|
||||
{
|
||||
// Calling this method constructs a new ref_ptr_t, which implicitly calls
|
||||
// intrusive_ptr_add_ref(MasterRefcount*).
|
||||
return &sMasterRefcount;
|
||||
}
|
||||
|
||||
void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount* mrc)
|
||||
{
|
||||
// Count outstanding SingletonLifetimeManager instances.
|
||||
++mrc->refcount;
|
||||
}
|
||||
|
||||
void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc)
|
||||
{
|
||||
// Notice when each SingletonLifetimeManager instance is destroyed.
|
||||
if (! --mrc->refcount)
|
||||
{
|
||||
// The last instance was destroyed. Time to kill any remaining
|
||||
// LLSingletons -- but in dependency order.
|
||||
LLSingletonBase::deleteAll();
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------- Logging helpers -----------------------------*/
|
||||
namespace {
|
||||
bool oktolog()
|
||||
{
|
||||
// See comments in log() below.
|
||||
return sMasterRefcount.refcount && LLError::is_available();
|
||||
return LLError::is_available();
|
||||
}
|
||||
|
||||
void log(LLError::ELevel level,
|
||||
const char* p1, const char* p2, const char* p3, const char* p4)
|
||||
{
|
||||
// Check whether we're in the implicit final LLSingletonBase::deleteAll()
|
||||
// call. We've carefully arranged for deleteAll() to be called when the
|
||||
// last SingletonLifetimeManager instance is destroyed -- in other words,
|
||||
// when the last translation unit containing an LLSingleton instance
|
||||
// cleans up static data. That could happen after std::cerr is destroyed!
|
||||
// The is_available() test below ensures that we'll stop logging once
|
||||
// LLError has been cleaned up. If we had a similar portable test for
|
||||
// std::cerr, this would be a good place to use it. As we do not, just
|
||||
// don't log anything during implicit final deleteAll(). Detect that by
|
||||
// the master refcount having gone to zero.
|
||||
if (sMasterRefcount.refcount == 0)
|
||||
return;
|
||||
// std::cerr, this would be a good place to use it.
|
||||
|
||||
// Check LLError::is_available() because some of LLError's infrastructure
|
||||
// is itself an LLSingleton. If that LLSingleton has not yet been
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <typeinfo>
|
||||
|
|
@ -36,8 +35,6 @@ class LLSingletonBase: private boost::noncopyable
|
|||
{
|
||||
public:
|
||||
class MasterList;
|
||||
class MasterRefcount;
|
||||
typedef boost::intrusive_ptr<MasterRefcount> ref_ptr_t;
|
||||
|
||||
private:
|
||||
// All existing LLSingleton instances are tracked in this master list.
|
||||
|
|
@ -119,9 +116,6 @@ protected:
|
|||
const char* p3="", const char* p4="");
|
||||
static std::string demangle(const char* mangled);
|
||||
|
||||
// obtain canonical ref_ptr_t
|
||||
static ref_ptr_t get_master_refcount();
|
||||
|
||||
// Default methods in case subclass doesn't declare them.
|
||||
virtual void initSingleton() {}
|
||||
virtual void cleanupSingleton() {}
|
||||
|
|
@ -175,10 +169,6 @@ public:
|
|||
static void deleteAll();
|
||||
};
|
||||
|
||||
// support ref_ptr_t
|
||||
void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount*);
|
||||
void intrusive_ptr_release(LLSingletonBase::MasterRefcount*);
|
||||
|
||||
// Most of the time, we want LLSingleton_manage_master() to forward its
|
||||
// methods to real LLSingletonBase methods.
|
||||
template <class T>
|
||||
|
|
@ -298,8 +288,7 @@ private:
|
|||
// stores pointer to singleton instance
|
||||
struct SingletonLifetimeManager
|
||||
{
|
||||
SingletonLifetimeManager():
|
||||
mMasterRefcount(LLSingletonBase::get_master_refcount())
|
||||
SingletonLifetimeManager()
|
||||
{
|
||||
construct();
|
||||
}
|
||||
|
|
@ -317,17 +306,14 @@ private:
|
|||
// of static-object destruction, mean that we DO NOT WANT this
|
||||
// destructor to delete this LLSingleton. This destructor will run
|
||||
// without regard to any other LLSingleton whose cleanup might
|
||||
// depend on its existence. What we really want is to count the
|
||||
// runtime's attempts to cleanup LLSingleton static data -- and on
|
||||
// the very last one, call LLSingletonBase::deleteAll(). That
|
||||
// method will properly honor cross-LLSingleton dependencies. This
|
||||
// is why we store an intrusive_ptr to a MasterRefcount: our
|
||||
// ref_ptr_t member counts SingletonLifetimeManager instances.
|
||||
// Once the runtime destroys the last of these, THEN we can delete
|
||||
// every remaining LLSingleton.
|
||||
// depend on its existence. If you want to clean up LLSingletons,
|
||||
// call LLSingletonBase::deleteAll() sometime before static-object
|
||||
// destruction begins. That method will properly honor cross-
|
||||
// LLSingleton dependencies. Otherwise we simply leak LLSingleton
|
||||
// instances at shutdown. Since the whole process is terminating
|
||||
// anyway, that's not necessarily a bad thing; it depends on what
|
||||
// resources your LLSingleton instances are managing.
|
||||
}
|
||||
|
||||
LLSingletonBase::ref_ptr_t mMasterRefcount;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
@ -452,6 +438,14 @@ public:
|
|||
return sData.mInitState == INITIALIZED;
|
||||
}
|
||||
|
||||
// Has this singleton been deleted? This can be useful during shutdown
|
||||
// processing to avoid "resurrecting" a singleton we thought we'd already
|
||||
// cleaned up.
|
||||
static bool wasDeleted()
|
||||
{
|
||||
return sData.mInitState == DELETED;
|
||||
}
|
||||
|
||||
private:
|
||||
struct SingletonData
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* @file llstatsaccumulator.h
|
||||
* @brief Class for accumulating statistics.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_STATS_ACCUMULATOR_H
|
||||
#define LL_STATS_ACCUMULATOR_H
|
||||
#include "llsd.h"
|
||||
|
||||
class LLStatsAccumulator
|
||||
{
|
||||
public:
|
||||
inline LLStatsAccumulator()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
inline void push(F32 val)
|
||||
{
|
||||
if (mCountOfNextUpdatesToIgnore > 0)
|
||||
{
|
||||
mCountOfNextUpdatesToIgnore--;
|
||||
return;
|
||||
}
|
||||
|
||||
mCount++;
|
||||
mSum += val;
|
||||
mSumOfSquares += val * val;
|
||||
if (mCount == 1 || val > mMaxValue)
|
||||
{
|
||||
mMaxValue = val;
|
||||
}
|
||||
if (mCount == 1 || val < mMinValue)
|
||||
{
|
||||
mMinValue = val;
|
||||
}
|
||||
}
|
||||
|
||||
inline F32 getSum() const
|
||||
{
|
||||
return mSum;
|
||||
}
|
||||
|
||||
inline F32 getMean() const
|
||||
{
|
||||
return (mCount == 0) ? 0.f : ((F32)mSum) / mCount;
|
||||
}
|
||||
|
||||
inline F32 getMinValue() const
|
||||
{
|
||||
return mMinValue;
|
||||
}
|
||||
|
||||
inline F32 getMaxValue() const
|
||||
{
|
||||
return mMaxValue;
|
||||
}
|
||||
|
||||
inline F32 getStdDev() const
|
||||
{
|
||||
const F32 mean = getMean();
|
||||
return (mCount < 2) ? 0.f : sqrt(llmax(0.f, mSumOfSquares / mCount - (mean * mean)));
|
||||
}
|
||||
|
||||
inline U32 getCount() const
|
||||
{
|
||||
return mCount;
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
mCount = 0;
|
||||
mSum = mSumOfSquares = 0.f;
|
||||
mMinValue = 0.0f;
|
||||
mMaxValue = 0.0f;
|
||||
mCountOfNextUpdatesToIgnore = 0;
|
||||
}
|
||||
|
||||
inline LLSD asLLSD() const
|
||||
{
|
||||
LLSD data;
|
||||
data["mean"] = getMean();
|
||||
data["std_dev"] = getStdDev();
|
||||
data["count"] = (S32)mCount;
|
||||
data["min"] = getMinValue();
|
||||
data["max"] = getMaxValue();
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mCount;
|
||||
F32 mSum;
|
||||
F32 mSumOfSquares;
|
||||
F32 mMinValue;
|
||||
F32 mMaxValue;
|
||||
U32 mCountOfNextUpdatesToIgnore;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -444,7 +444,7 @@ public:
|
|||
struct LLDictionaryLess
|
||||
{
|
||||
public:
|
||||
bool operator()(const std::string& a, const std::string& b)
|
||||
bool operator()(const std::string& a, const std::string& b) const
|
||||
{
|
||||
return (LLStringUtil::precedesDict(a, b) ? true : false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ using namespace llsd;
|
|||
#if LL_WINDOWS
|
||||
# include "llwin32headerslean.h"
|
||||
# include <psapi.h> // GetPerformanceInfo() et al.
|
||||
# include <VersionHelpers.h>
|
||||
#elif LL_DARWIN
|
||||
# include <errno.h>
|
||||
# include <sys/sysctl.h>
|
||||
|
|
@ -110,78 +111,6 @@ static const F32 MEM_INFO_THROTTLE = 20;
|
|||
// dropped below the login framerate, we'd have very little additional data.
|
||||
static const F32 MEM_INFO_WINDOW = 10*60;
|
||||
|
||||
#if LL_WINDOWS
|
||||
// We cannot trust GetVersionEx function on Win8.1 , we should check this value when creating OS string
|
||||
static const U32 WINNT_WINBLUE = 0x0603;
|
||||
|
||||
#ifndef DLLVERSIONINFO
|
||||
typedef struct _DllVersionInfo
|
||||
{
|
||||
DWORD cbSize;
|
||||
DWORD dwMajorVersion;
|
||||
DWORD dwMinorVersion;
|
||||
DWORD dwBuildNumber;
|
||||
DWORD dwPlatformID;
|
||||
}DLLVERSIONINFO;
|
||||
#endif
|
||||
|
||||
#ifndef DLLGETVERSIONPROC
|
||||
typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
|
||||
#endif
|
||||
|
||||
bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)
|
||||
{
|
||||
bool result = false;
|
||||
const U32 BUFF_SIZE = 32767;
|
||||
WCHAR tempBuf[BUFF_SIZE];
|
||||
if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE))
|
||||
{
|
||||
|
||||
std::basic_string<WCHAR> shell32_path(tempBuf);
|
||||
|
||||
// Shell32.dll contains the DLLGetVersion function.
|
||||
// according to msdn its not part of the API
|
||||
// so you have to go in and get it.
|
||||
// http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx
|
||||
shell32_path += TEXT("\\shell32.dll");
|
||||
|
||||
HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL
|
||||
if(hDllInst)
|
||||
{ // Could successfully load the DLL
|
||||
DLLGETVERSIONPROC pDllGetVersion;
|
||||
/*
|
||||
You must get this function explicitly because earlier versions of the DLL
|
||||
don't implement this function. That makes the lack of implementation of the
|
||||
function a version marker in itself.
|
||||
*/
|
||||
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst,
|
||||
"DllGetVersion");
|
||||
|
||||
if(pDllGetVersion)
|
||||
{
|
||||
// DLL supports version retrieval function
|
||||
DLLVERSIONINFO dvi;
|
||||
|
||||
ZeroMemory(&dvi, sizeof(dvi));
|
||||
dvi.cbSize = sizeof(dvi);
|
||||
HRESULT hr = (*pDllGetVersion)(&dvi);
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{ // Finally, the version is at our hands
|
||||
major = dvi.dwMajorVersion;
|
||||
minor = dvi.dwMinorVersion;
|
||||
build_number = dvi.dwBuildNumber;
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary(hDllInst); // Release DLL
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
// Wrap boost::regex_match() with a function that doesn't throw.
|
||||
template <typename S, typename M, typename R>
|
||||
static bool regex_match_no_exc(const S& string, M& match, const R& regex)
|
||||
|
|
@ -214,221 +143,139 @@ static bool regex_search_no_exc(const S& string, M& match, const R& regex)
|
|||
}
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
// GetVersionEx should not works correct with Windows 8.1 and the later version. We need to check this case
|
||||
static bool check_for_version(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
VerSetConditionMask(
|
||||
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION, VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
||||
|
||||
osvi.dwMajorVersion = wMajorVersion;
|
||||
osvi.dwMinorVersion = wMinorVersion;
|
||||
osvi.wServicePackMajor = wServicePackMajor;
|
||||
|
||||
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
LLOSInfo::LLOSInfo() :
|
||||
mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
|
||||
{
|
||||
|
||||
#if LL_WINDOWS
|
||||
OSVERSIONINFOEX osvi;
|
||||
BOOL bOsVersionInfoEx;
|
||||
BOOL bShouldUseShellVersion = false;
|
||||
|
||||
if (IsWindowsVersionOrGreater(10, 0, 0))
|
||||
{
|
||||
mMajorVer = 10;
|
||||
mMinorVer = 0;
|
||||
mOSStringSimple = "Microsoft Windows 10 ";
|
||||
}
|
||||
else if (IsWindows8Point1OrGreater())
|
||||
{
|
||||
mMajorVer = 6;
|
||||
mMinorVer = 3;
|
||||
if (IsWindowsServer())
|
||||
{
|
||||
mOSStringSimple = "Windows Server 2012 R2 ";
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 8.1 ";
|
||||
}
|
||||
}
|
||||
else if (IsWindows8OrGreater())
|
||||
{
|
||||
mMajorVer = 6;
|
||||
mMinorVer = 2;
|
||||
if (IsWindowsServer())
|
||||
{
|
||||
mOSStringSimple = "Windows Server 2012 ";
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 8 ";
|
||||
}
|
||||
}
|
||||
else if (IsWindows7SP1OrGreater())
|
||||
{
|
||||
mMajorVer = 6;
|
||||
mMinorVer = 1;
|
||||
if (IsWindowsServer())
|
||||
{
|
||||
mOSStringSimple = "Windows Server 2008 R2 SP1 ";
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 7 SP1 ";
|
||||
}
|
||||
}
|
||||
else if (IsWindows7OrGreater())
|
||||
{
|
||||
mMajorVer = 6;
|
||||
mMinorVer = 1;
|
||||
if (IsWindowsServer())
|
||||
{
|
||||
mOSStringSimple = "Windows Server 2008 R2 ";
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 7 ";
|
||||
}
|
||||
}
|
||||
else if (IsWindowsVistaSP2OrGreater())
|
||||
{
|
||||
mMajorVer = 6;
|
||||
mMinorVer = 0;
|
||||
if (IsWindowsServer())
|
||||
{
|
||||
mOSStringSimple = "Windows Server 2008 SP2 ";
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows Vista SP2 ";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mOSStringSimple = "Unsupported Windows version ";
|
||||
}
|
||||
|
||||
///get native system info if available..
|
||||
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
|
||||
SYSTEM_INFO si; //System Info object file contains architecture info
|
||||
PGNSI pGNSI; //pointer object
|
||||
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
|
||||
pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
|
||||
if (NULL != pGNSI) //check if it has failed
|
||||
pGNSI(&si); //success
|
||||
else
|
||||
GetSystemInfo(&si); //if it fails get regular system info
|
||||
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
|
||||
|
||||
//msdn microsoft finds 32 bit and 64 bit flavors this way..
|
||||
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
|
||||
//of windows than this code does (in case it is needed for the future)
|
||||
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
|
||||
{
|
||||
mOSStringSimple += "64-bit ";
|
||||
}
|
||||
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
||||
{
|
||||
mOSStringSimple += "32-bit ";
|
||||
}
|
||||
|
||||
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
|
||||
OSVERSIONINFOEX osvi;
|
||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
|
||||
if (GetVersionEx((OSVERSIONINFO *)&osvi))
|
||||
{
|
||||
mBuild = osvi.dwBuildNumber & 0xffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
|
||||
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
||||
if(!GetVersionEx( (OSVERSIONINFO *) &osvi))
|
||||
return;
|
||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if (GetVersionEx((OSVERSIONINFO *)&osvi))
|
||||
{
|
||||
mBuild = osvi.dwBuildNumber & 0xffff;
|
||||
}
|
||||
}
|
||||
mMajorVer = osvi.dwMajorVersion;
|
||||
mMinorVer = osvi.dwMinorVersion;
|
||||
mBuild = osvi.dwBuildNumber;
|
||||
|
||||
DWORD shell32_major, shell32_minor, shell32_build;
|
||||
bool got_shell32_version = get_shell32_dll_version(shell32_major,
|
||||
shell32_minor,
|
||||
shell32_build);
|
||||
|
||||
switch(osvi.dwPlatformId)
|
||||
mOSString = mOSStringSimple;
|
||||
if (mBuild > 0)
|
||||
{
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
{
|
||||
// Test for the product.
|
||||
if(osvi.dwMajorVersion <= 4)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows NT ";
|
||||
}
|
||||
else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 2000 ";
|
||||
}
|
||||
else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows XP ";
|
||||
}
|
||||
else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
|
||||
{
|
||||
if(osvi.wProductType == VER_NT_WORKSTATION)
|
||||
mOSStringSimple = "Microsoft Windows XP x64 Edition ";
|
||||
else
|
||||
mOSStringSimple = "Microsoft Windows Server 2003 ";
|
||||
}
|
||||
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 2)
|
||||
{
|
||||
if(osvi.dwMinorVersion == 0)
|
||||
{
|
||||
if(osvi.wProductType == VER_NT_WORKSTATION)
|
||||
mOSStringSimple = "Microsoft Windows Vista ";
|
||||
else
|
||||
mOSStringSimple = "Windows Server 2008 ";
|
||||
}
|
||||
else if(osvi.dwMinorVersion == 1)
|
||||
{
|
||||
if(osvi.wProductType == VER_NT_WORKSTATION)
|
||||
mOSStringSimple = "Microsoft Windows 7 ";
|
||||
else
|
||||
mOSStringSimple = "Windows Server 2008 R2 ";
|
||||
}
|
||||
else if(osvi.dwMinorVersion == 2)
|
||||
{
|
||||
if (check_for_version(HIBYTE(WINNT_WINBLUE), LOBYTE(WINNT_WINBLUE), 0))
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 8.1 ";
|
||||
bShouldUseShellVersion = true; // GetVersionEx failed, going to use shell version
|
||||
}
|
||||
else
|
||||
{
|
||||
if(osvi.wProductType == VER_NT_WORKSTATION)
|
||||
mOSStringSimple = "Microsoft Windows 8 ";
|
||||
else
|
||||
mOSStringSimple = "Windows Server 2012 ";
|
||||
}
|
||||
}
|
||||
|
||||
///get native system info if available..
|
||||
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
|
||||
SYSTEM_INFO si; //System Info object file contains architecture info
|
||||
PGNSI pGNSI; //pointer object
|
||||
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
|
||||
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
|
||||
if(NULL != pGNSI) //check if it has failed
|
||||
pGNSI(&si); //success
|
||||
else
|
||||
GetSystemInfo(&si); //if it fails get regular system info
|
||||
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
|
||||
|
||||
//msdn microsoft finds 32 bit and 64 bit flavors this way..
|
||||
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
|
||||
//of windows than this code does (in case it is needed for the future)
|
||||
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
|
||||
{
|
||||
mOSStringSimple += "64-bit ";
|
||||
}
|
||||
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
|
||||
{
|
||||
mOSStringSimple += "32-bit ";
|
||||
}
|
||||
}
|
||||
else // Use the registry on early versions of Windows NT.
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows (unrecognized) ";
|
||||
|
||||
HKEY hKey;
|
||||
WCHAR szProductType[80];
|
||||
DWORD dwBufLen;
|
||||
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
|
||||
0, KEY_QUERY_VALUE, &hKey );
|
||||
RegQueryValueEx( hKey, L"ProductType", NULL, NULL,
|
||||
(LPBYTE) szProductType, &dwBufLen);
|
||||
RegCloseKey( hKey );
|
||||
if ( lstrcmpi( L"WINNT", szProductType) == 0 )
|
||||
{
|
||||
mOSStringSimple += "Professional ";
|
||||
}
|
||||
else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 )
|
||||
{
|
||||
mOSStringSimple += "Server ";
|
||||
}
|
||||
else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 )
|
||||
{
|
||||
mOSStringSimple += "Advanced Server ";
|
||||
}
|
||||
}
|
||||
|
||||
std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion);
|
||||
// Display version, service pack (if any), and build number.
|
||||
std::string tmpstr;
|
||||
if(osvi.dwMajorVersion <= 4)
|
||||
{
|
||||
tmpstr = llformat("version %d.%d %s (Build %d)",
|
||||
osvi.dwMajorVersion,
|
||||
osvi.dwMinorVersion,
|
||||
csdversion.c_str(),
|
||||
(osvi.dwBuildNumber & 0xffff));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpstr = !bShouldUseShellVersion ? llformat("%s (Build %d)", csdversion.c_str(), (osvi.dwBuildNumber & 0xffff)):
|
||||
llformat("%s (Build %d)", csdversion.c_str(), shell32_build);
|
||||
}
|
||||
|
||||
mOSString = mOSStringSimple + tmpstr;
|
||||
}
|
||||
break;
|
||||
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
// Test for the Windows 95 product family.
|
||||
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 95 ";
|
||||
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
|
||||
{
|
||||
mOSStringSimple += "OSR2 ";
|
||||
}
|
||||
}
|
||||
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows 98 ";
|
||||
if ( osvi.szCSDVersion[1] == 'A' )
|
||||
{
|
||||
mOSStringSimple += "SE ";
|
||||
}
|
||||
}
|
||||
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
|
||||
{
|
||||
mOSStringSimple = "Microsoft Windows Millennium Edition ";
|
||||
}
|
||||
mOSString = mOSStringSimple;
|
||||
break;
|
||||
mOSString += llformat("(Build %d)", mBuild);
|
||||
}
|
||||
|
||||
std::string compatibility_mode;
|
||||
if(got_shell32_version)
|
||||
{
|
||||
if((osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) && !bShouldUseShellVersion)
|
||||
{
|
||||
compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
|
||||
shell32_major,
|
||||
shell32_minor,
|
||||
shell32_build);
|
||||
}
|
||||
}
|
||||
mOSString += compatibility_mode;
|
||||
LLStringUtil::trim(mOSStringSimple);
|
||||
LLStringUtil::trim(mOSString);
|
||||
|
||||
#elif LL_DARWIN
|
||||
|
||||
|
|
@ -914,22 +761,6 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
|
|||
#endif
|
||||
}
|
||||
|
||||
U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||
{
|
||||
// Return the total physical memory in bytes, but clamp it
|
||||
// to no more than U32_MAX
|
||||
|
||||
U32Kilobytes phys_kb = getPhysicalMemoryKB();
|
||||
if (phys_kb >= U32Gigabytes(4))
|
||||
{
|
||||
return U32Bytes(U32_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
return phys_kb;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
|
||||
{
|
||||
|
|
@ -1144,10 +975,10 @@ LLSD LLMemoryInfo::loadStatsMap()
|
|||
//
|
||||
|
||||
{
|
||||
vm_statistics_data_t vmstat;
|
||||
mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT;
|
||||
vm_statistics64_data_t vmstat;
|
||||
mach_msg_type_number_t vmstatCount = HOST_VM_INFO64_COUNT;
|
||||
|
||||
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
|
||||
if (host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
|
||||
{
|
||||
LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
|
||||
}
|
||||
|
|
@ -1205,20 +1036,20 @@ LLSD LLMemoryInfo::loadStatsMap()
|
|||
//
|
||||
|
||||
{
|
||||
task_basic_info_64_data_t taskinfo;
|
||||
unsigned taskinfoSize = sizeof(taskinfo);
|
||||
|
||||
if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS)
|
||||
mach_task_basic_info_data_t taskinfo;
|
||||
mach_msg_type_number_t task_count = MACH_TASK_BASIC_INFO_COUNT;
|
||||
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &taskinfo, &task_count) != KERN_SUCCESS)
|
||||
{
|
||||
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.add("Basic suspend count", taskinfo.suspend_count);
|
||||
stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
|
||||
stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
|
||||
stats.add("Basic new thread policy", taskinfo.policy);
|
||||
}
|
||||
LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024);
|
||||
stats.add("Basic resident memory KB", taskinfo.resident_size / 1024);
|
||||
stats.add("Basic max resident memory KB", taskinfo.resident_size_max / 1024);
|
||||
stats.add("Basic new thread policy", taskinfo.policy);
|
||||
stats.add("Basic suspend count", taskinfo.suspend_count);
|
||||
}
|
||||
}
|
||||
|
||||
#elif LL_SOLARIS
|
||||
|
|
|
|||
|
|
@ -114,11 +114,6 @@ public:
|
|||
void stream(std::ostream& s) const; ///< output text info to s
|
||||
|
||||
U32Kilobytes getPhysicalMemoryKB() const;
|
||||
|
||||
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
|
||||
** be returned.
|
||||
*/
|
||||
U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
|
||||
|
||||
//get the available memory infomation in KiloBytes.
|
||||
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "lltrace.h"
|
||||
#include "lltracethreadrecorder.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#include <sched.h>
|
||||
|
|
@ -46,28 +47,28 @@ const DWORD MS_VC_EXCEPTION=0x406D1388;
|
|||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
void set_thread_name( DWORD dwThreadID, const char* threadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
__try
|
||||
{
|
||||
::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -99,17 +100,17 @@ U32 LLThread::sIDIter = 0;
|
|||
|
||||
LL_COMMON_API void assert_main_thread()
|
||||
{
|
||||
static U32 s_thread_id = LLThread::currentID();
|
||||
if (LLThread::currentID() != s_thread_id)
|
||||
{
|
||||
LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
|
||||
<< " outside main thread " << (S32) s_thread_id << LL_ENDL;
|
||||
}
|
||||
static U32 s_thread_id = LLThread::currentID();
|
||||
if (LLThread::currentID() != s_thread_id)
|
||||
{
|
||||
LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
|
||||
<< " outside main thread " << (S32) s_thread_id << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::registerThreadID()
|
||||
{
|
||||
sThreadID = ++sIDIter;
|
||||
sThreadID = ++sIDIter;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -117,157 +118,203 @@ void LLThread::registerThreadID()
|
|||
//
|
||||
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
|
||||
{
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
set_thread_name(-1, threadp->mName.c_str());
|
||||
set_thread_name(-1, threadp->mName.c_str());
|
||||
#endif
|
||||
|
||||
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
|
||||
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
|
||||
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
|
||||
sThreadID = threadp->mID;
|
||||
sThreadID = threadp->mID;
|
||||
|
||||
// Run the user supplied function
|
||||
threadp->run();
|
||||
try
|
||||
{
|
||||
// Run the user supplied function
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
threadp->run();
|
||||
}
|
||||
catch (const LLContinueError &e)
|
||||
{
|
||||
LL_WARNS("THREAD") << "ContinueException on thread '" << threadp->mName <<
|
||||
"' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
|
||||
|
||||
delete threadp->mRecorder;
|
||||
threadp->mRecorder = NULL;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
//NB: we are using this flag to sync across threads...we really need memory barriers here
|
||||
threadp->mStatus = STOPPED;
|
||||
LOG_UNHANDLED_EXCEPTION("LLThread");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
return NULL;
|
||||
} while (true);
|
||||
|
||||
//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
//NB: we are using this flag to sync across threads...we really need memory barriers here
|
||||
threadp->mStatus = STOPPED;
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
threadp->mStatus = CRASHED;
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_ERRS("THREAD") << "Bad memory allocation in LLThread::staticRun() named '" << threadp->mName << "'!" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
threadp->mStatus = CRASHED;
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("LLThread");
|
||||
}
|
||||
|
||||
delete threadp->mRecorder;
|
||||
threadp->mRecorder = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED),
|
||||
mRecorder(NULL)
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED),
|
||||
mRecorder(NULL)
|
||||
{
|
||||
|
||||
mID = ++sIDIter;
|
||||
mID = ++sIDIter;
|
||||
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
|
||||
|
||||
LLThread::~LLThread()
|
||||
{
|
||||
shutdown();
|
||||
shutdown();
|
||||
|
||||
if(mLocalAPRFilePoolp)
|
||||
{
|
||||
delete mLocalAPRFilePoolp ;
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
if (isCrashed())
|
||||
{
|
||||
LL_WARNS("THREAD") << "Destroying crashed thread named '" << mName << "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
if(mLocalAPRFilePoolp)
|
||||
{
|
||||
delete mLocalAPRFilePoolp ;
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::shutdown()
|
||||
{
|
||||
// Warning! If you somehow call the thread destructor from itself,
|
||||
// the thread will die in an unclean fashion!
|
||||
if (mAPRThreadp)
|
||||
{
|
||||
if (!isStopped())
|
||||
{
|
||||
// The thread isn't already stopped
|
||||
// First, set the flag that indicates that we're ready to die
|
||||
setQuitting();
|
||||
if (isCrashed())
|
||||
{
|
||||
LL_WARNS("THREAD") << "Shutting down crashed thread named '" << mName << "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
|
||||
// Now wait a bit for the thread to exit
|
||||
// It's unclear whether I should even bother doing this - this destructor
|
||||
// should never get called unless we're already stopped, really...
|
||||
S32 counter = 0;
|
||||
const S32 MAX_WAIT = 600;
|
||||
while (counter < MAX_WAIT)
|
||||
{
|
||||
if (isStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Sleep for a tenth of a second
|
||||
ms_sleep(100);
|
||||
yield();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
// Warning! If you somehow call the thread destructor from itself,
|
||||
// the thread will die in an unclean fashion!
|
||||
if (mAPRThreadp)
|
||||
{
|
||||
if (!isStopped())
|
||||
{
|
||||
// The thread isn't already stopped
|
||||
// First, set the flag that indicates that we're ready to die
|
||||
setQuitting();
|
||||
|
||||
if (!isStopped())
|
||||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
|
||||
// Put a stake in its heart.
|
||||
delete mRecorder;
|
||||
//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
|
||||
// Now wait a bit for the thread to exit
|
||||
// It's unclear whether I should even bother doing this - this destructor
|
||||
// should never get called unless we're already stopped, really...
|
||||
S32 counter = 0;
|
||||
const S32 MAX_WAIT = 600;
|
||||
while (counter < MAX_WAIT)
|
||||
{
|
||||
if (isStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Sleep for a tenth of a second
|
||||
ms_sleep(100);
|
||||
yield();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
apr_thread_exit(mAPRThreadp, -1);
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
}
|
||||
if (!isStopped())
|
||||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
|
||||
// Put a stake in its heart.
|
||||
delete mRecorder;
|
||||
|
||||
delete mRunCondition;
|
||||
mRunCondition = NULL;
|
||||
apr_thread_exit(mAPRThreadp, -1);
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
}
|
||||
|
||||
delete mDataLock;
|
||||
mDataLock = NULL;
|
||||
|
||||
if (mIsLocalPool && mAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
mAPRPoolp = 0;
|
||||
}
|
||||
delete mRunCondition;
|
||||
mRunCondition = NULL;
|
||||
|
||||
if (mRecorder)
|
||||
{
|
||||
// missed chance to properly shut down recorder (needs to be done in thread context)
|
||||
// probably due to abnormal thread termination
|
||||
// so just leak it and remove it from parent
|
||||
LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
|
||||
}
|
||||
delete mDataLock;
|
||||
mDataLock = NULL;
|
||||
|
||||
if (mIsLocalPool && mAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
mAPRPoolp = 0;
|
||||
}
|
||||
|
||||
if (mRecorder)
|
||||
{
|
||||
// missed chance to properly shut down recorder (needs to be done in thread context)
|
||||
// probably due to abnormal thread termination
|
||||
// so just leak it and remove it from parent
|
||||
LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLThread::start()
|
||||
{
|
||||
llassert(isStopped());
|
||||
|
||||
// Set thread state to running
|
||||
mStatus = RUNNING;
|
||||
llassert(isStopped());
|
||||
|
||||
// Set thread state to running
|
||||
mStatus = RUNNING;
|
||||
|
||||
apr_status_t status =
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mStatus = STOPPED;
|
||||
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
|
||||
ll_apr_warn_status(status);
|
||||
}
|
||||
apr_status_t status =
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mStatus = STOPPED;
|
||||
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
|
||||
ll_apr_warn_status(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -278,28 +325,28 @@ void LLThread::start()
|
|||
// The thread will pause when (and if) it calls checkPause()
|
||||
void LLThread::pause()
|
||||
{
|
||||
if (!mPaused)
|
||||
{
|
||||
// this will cause the thread to stop execution as soon as checkPause() is called
|
||||
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
|
||||
}
|
||||
if (!mPaused)
|
||||
{
|
||||
// this will cause the thread to stop execution as soon as checkPause() is called
|
||||
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::unpause()
|
||||
{
|
||||
if (mPaused)
|
||||
{
|
||||
mPaused = 0;
|
||||
}
|
||||
if (mPaused)
|
||||
{
|
||||
mPaused = 0;
|
||||
}
|
||||
|
||||
wake(); // wake up the thread if necessary
|
||||
wake(); // wake up the thread if necessary
|
||||
}
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
bool LLThread::runCondition(void)
|
||||
{
|
||||
// by default, always run. Handling of pause/unpause is done regardless of this function's result.
|
||||
return true;
|
||||
// by default, always run. Handling of pause/unpause is done regardless of this function's result.
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -307,65 +354,65 @@ bool LLThread::runCondition(void)
|
|||
// Stop thread execution if requested until unpaused.
|
||||
void LLThread::checkPause()
|
||||
{
|
||||
mDataLock->lock();
|
||||
mDataLock->lock();
|
||||
|
||||
// This is in a while loop because the pthread API allows for spurious wakeups.
|
||||
while(shouldSleep())
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mRunCondition->wait(); // unlocks mRunCondition
|
||||
mDataLock->lock();
|
||||
// mRunCondition is locked when the thread wakes up
|
||||
}
|
||||
|
||||
mDataLock->unlock();
|
||||
// This is in a while loop because the pthread API allows for spurious wakeups.
|
||||
while(shouldSleep())
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mRunCondition->wait(); // unlocks mRunCondition
|
||||
mDataLock->lock();
|
||||
// mRunCondition is locked when the thread wakes up
|
||||
}
|
||||
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
void LLThread::setQuitting()
|
||||
{
|
||||
mDataLock->lock();
|
||||
if (mStatus == RUNNING)
|
||||
{
|
||||
mStatus = QUITTING;
|
||||
}
|
||||
mDataLock->unlock();
|
||||
wake();
|
||||
mDataLock->lock();
|
||||
if (mStatus == RUNNING)
|
||||
{
|
||||
mStatus = QUITTING;
|
||||
}
|
||||
mDataLock->unlock();
|
||||
wake();
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLThread::currentID()
|
||||
{
|
||||
return sThreadID;
|
||||
return sThreadID;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLThread::yield()
|
||||
{
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
|
||||
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
|
||||
#else
|
||||
apr_thread_yield();
|
||||
apr_thread_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLThread::wake()
|
||||
{
|
||||
mDataLock->lock();
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
mDataLock->unlock();
|
||||
mDataLock->lock();
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
void LLThread::wakeLocked()
|
||||
{
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -378,38 +425,38 @@ LLMutex* LLThreadSafeRefCount::sMutex = 0;
|
|||
//static
|
||||
void LLThreadSafeRefCount::initThreadSafeRefCount()
|
||||
{
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
}
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
|
||||
{
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LLThreadSafeRefCount::LLThreadSafeRefCount() :
|
||||
mRef(0)
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
|
||||
{
|
||||
mRef = 0;
|
||||
mRef = 0;
|
||||
}
|
||||
|
||||
LLThreadSafeRefCount::~LLThreadSafeRefCount()
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
LL_ERRS() << "deleting referenced object mRef = " << mRef << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -38,118 +38,120 @@ LL_COMMON_API void assert_main_thread();
|
|||
|
||||
namespace LLTrace
|
||||
{
|
||||
class ThreadRecorder;
|
||||
class ThreadRecorder;
|
||||
}
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
private:
|
||||
friend class LLMutex;
|
||||
static U32 sIDIter;
|
||||
friend class LLMutex;
|
||||
static U32 sIDIter;
|
||||
|
||||
public:
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2 // Someone wants this thread to quit
|
||||
} EThreadStatus;
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2, // Someone wants this thread to quit
|
||||
CRASHED = -1 // An uncaught exception was thrown by the thread
|
||||
} EThreadStatus;
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); }
|
||||
bool isCrashed() const { return (CRASHED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
public:
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
|
||||
U32 getID() const { return mID; }
|
||||
U32 getID() const { return mID; }
|
||||
|
||||
// Called by threads *not* created via LLThread to register some
|
||||
// internal state used by LLMutex. You must call this once early
|
||||
// in the running thread to prevent collisions with the main thread.
|
||||
static void registerThreadID();
|
||||
|
||||
// Called by threads *not* created via LLThread to register some
|
||||
// internal state used by LLMutex. You must call this once early
|
||||
// in the running thread to prevent collisions with the main thread.
|
||||
static void registerThreadID();
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
|
||||
|
||||
protected:
|
||||
std::string mName;
|
||||
class LLCondition* mRunCondition;
|
||||
LLMutex* mDataLock;
|
||||
std::string mName;
|
||||
class LLCondition* mRunCondition;
|
||||
LLMutex* mDataLock;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
LLTrace::ThreadRecorder* mRecorder;
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
LLTrace::ThreadRecorder* mRecorder;
|
||||
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mDataLock->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mDataLock->unlock();
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mDataLock->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mDataLock->unlock();
|
||||
};
|
||||
|
||||
|
||||
void LLThread::lockData()
|
||||
{
|
||||
mDataLock->lock();
|
||||
mDataLock->lock();
|
||||
}
|
||||
|
||||
void LLThread::unlockData()
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -160,9 +162,9 @@ void LLThread::unlockData()
|
|||
class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
|
||||
{
|
||||
protected:
|
||||
virtual ~LLResponder();
|
||||
virtual ~LLResponder();
|
||||
public:
|
||||
virtual void completed(bool success) = 0;
|
||||
virtual void completed(bool success) = 0;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class StatBase
|
|||
{
|
||||
public:
|
||||
StatBase(const char* name, const char* description);
|
||||
virtual ~StatBase() {};
|
||||
virtual ~StatBase() LLINSTANCETRACKER_DTOR_NOEXCEPT {}
|
||||
virtual const char* getUnitLabel() const;
|
||||
|
||||
const std::string& getName() const { return mName; }
|
||||
|
|
|
|||
|
|
@ -788,6 +788,69 @@ namespace tut
|
|||
|
||||
template<> template<>
|
||||
void object::test<10>()
|
||||
{
|
||||
set_test_name("attached=false");
|
||||
// almost just like autokill=false, except set autokill=true with
|
||||
// attached=false.
|
||||
NamedTempFile from("from", "not started");
|
||||
NamedTempFile to("to", "");
|
||||
LLProcess::handle phandle(0);
|
||||
{
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
"from __future__ import with_statement\n"
|
||||
"import sys, time\n"
|
||||
"with open(sys.argv[1], 'w') as f:\n"
|
||||
" f.write('ok')\n"
|
||||
"# wait for 'go' from test program\n"
|
||||
"for i in xrange(60):\n"
|
||||
" time.sleep(1)\n"
|
||||
" with open(sys.argv[2]) as f:\n"
|
||||
" go = f.read()\n"
|
||||
" if go == 'go':\n"
|
||||
" break\n"
|
||||
"else:\n"
|
||||
" with open(sys.argv[1], 'w') as f:\n"
|
||||
" f.write('never saw go')\n"
|
||||
" sys.exit(1)\n"
|
||||
"# okay, saw 'go', write 'ack'\n"
|
||||
"with open(sys.argv[1], 'w') as f:\n"
|
||||
" f.write('ack')\n");
|
||||
py.mParams.args.add(from.getName());
|
||||
py.mParams.args.add(to.getName());
|
||||
py.mParams.autokill = true;
|
||||
py.mParams.attached = false;
|
||||
py.launch();
|
||||
// Capture handle for later
|
||||
phandle = py.mPy->getProcessHandle();
|
||||
// Wait for the script to wake up and do its first write
|
||||
int i = 0, timeout = 60;
|
||||
for ( ; i < timeout; ++i)
|
||||
{
|
||||
yield();
|
||||
if (readfile(from.getName(), "from autokill script") == "ok")
|
||||
break;
|
||||
}
|
||||
// If we broke this loop because of the counter, something's wrong
|
||||
ensure("script never started", i < timeout);
|
||||
// Now destroy the LLProcess, which should NOT kill the child!
|
||||
}
|
||||
// If the destructor killed the child anyway, give it time to die
|
||||
yield(2);
|
||||
// How do we know it's not terminated? By making it respond to
|
||||
// a specific stimulus in a specific way.
|
||||
{
|
||||
std::ofstream outf(to.getName().c_str());
|
||||
outf << "go";
|
||||
} // flush and close.
|
||||
// now wait for the script to terminate... one way or another.
|
||||
waitfor(phandle, "autokill script");
|
||||
// If the LLProcess destructor implicitly called kill(), the
|
||||
// script could not have written 'ack' as we expect.
|
||||
ensure_equals(get_test_name() + " script output", readfile(from.getName()), "ack");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<11>()
|
||||
{
|
||||
set_test_name("'bogus' test");
|
||||
CaptureLog recorder;
|
||||
|
|
@ -801,7 +864,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<11>()
|
||||
void object::test<12>()
|
||||
{
|
||||
set_test_name("'file' test");
|
||||
// Replace this test with one or more real 'file' tests when we
|
||||
|
|
@ -815,7 +878,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<12>()
|
||||
void object::test<13>()
|
||||
{
|
||||
set_test_name("'tpipe' test");
|
||||
// Replace this test with one or more real 'tpipe' tests when we
|
||||
|
|
@ -832,7 +895,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<13>()
|
||||
void object::test<14>()
|
||||
{
|
||||
set_test_name("'npipe' test");
|
||||
// Replace this test with one or more real 'npipe' tests when we
|
||||
|
|
@ -850,7 +913,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<14>()
|
||||
void object::test<15>()
|
||||
{
|
||||
set_test_name("internal pipe name warning");
|
||||
CaptureLog recorder;
|
||||
|
|
@ -914,7 +977,7 @@ namespace tut
|
|||
} while (0)
|
||||
|
||||
template<> template<>
|
||||
void object::test<15>()
|
||||
void object::test<16>()
|
||||
{
|
||||
set_test_name("get*Pipe() validation");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -934,7 +997,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<16>()
|
||||
void object::test<17>()
|
||||
{
|
||||
set_test_name("talk to stdin/stdout");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -992,7 +1055,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<17>()
|
||||
void object::test<18>()
|
||||
{
|
||||
set_test_name("listen for ReadPipe events");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -1052,7 +1115,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<18>()
|
||||
void object::test<19>()
|
||||
{
|
||||
set_test_name("ReadPipe \"eof\" event");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -1078,7 +1141,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<19>()
|
||||
void object::test<20>()
|
||||
{
|
||||
set_test_name("setLimit()");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -1107,7 +1170,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<20>()
|
||||
void object::test<21>()
|
||||
{
|
||||
set_test_name("peek() ReadPipe data");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -1160,7 +1223,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<21>()
|
||||
void object::test<22>()
|
||||
{
|
||||
set_test_name("bad postend");
|
||||
std::string pumpname("postend");
|
||||
|
|
@ -1185,7 +1248,7 @@ namespace tut
|
|||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<22>()
|
||||
void object::test<23>()
|
||||
{
|
||||
set_test_name("good postend");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
@ -1241,7 +1304,7 @@ namespace tut
|
|||
};
|
||||
|
||||
template<> template<>
|
||||
void object::test<23>()
|
||||
void object::test<24>()
|
||||
{
|
||||
set_test_name("all data visible at postend");
|
||||
PythonProcessLauncher py(get_test_name(),
|
||||
|
|
|
|||
|
|
@ -1553,7 +1553,7 @@ namespace tut
|
|||
params.executable = PYTHON;
|
||||
params.args.add(scriptfile.getName());
|
||||
LLProcessPtr py(LLProcess::create(params));
|
||||
ensure(STRINGIZE("Couldn't launch " << desc << " script"), py);
|
||||
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
|
||||
// Implementing timeout would mean messing with alarm() and
|
||||
// catching SIGALRM... later maybe...
|
||||
int status(0);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ include(00-Common)
|
|||
include(GoogleMock)
|
||||
include(CURL)
|
||||
include(OpenSSL)
|
||||
include(NGHTTP2)
|
||||
include(ZLIB)
|
||||
include(LLCoreHttp)
|
||||
include(LLAddBuildTest)
|
||||
|
|
@ -30,6 +31,7 @@ set(llcorehttp_SOURCE_FILES
|
|||
httpoptions.cpp
|
||||
httprequest.cpp
|
||||
httpresponse.cpp
|
||||
httpstats.cpp
|
||||
_httplibcurl.cpp
|
||||
_httpopcancel.cpp
|
||||
_httpoperation.cpp
|
||||
|
|
@ -57,6 +59,7 @@ set(llcorehttp_HEADER_FILES
|
|||
httpoptions.h
|
||||
httprequest.h
|
||||
httpresponse.h
|
||||
httpstats.h
|
||||
_httpinternal.h
|
||||
_httplibcurl.h
|
||||
_httpopcancel.h
|
||||
|
|
@ -92,6 +95,7 @@ target_link_libraries(
|
|||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
${NGHTTP2_LIBRARIES}
|
||||
${BOOST_THREAD_LIBRARY}
|
||||
${BOOST_SYSTEM_LIBRARY}
|
||||
)
|
||||
|
|
@ -130,6 +134,7 @@ if (LL_TESTS)
|
|||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
${NGHTTP2_LIBRARIES}
|
||||
${BOOST_THREAD_LIBRARY}
|
||||
${BOOST_SYSTEM_LIBRARY}
|
||||
)
|
||||
|
|
@ -137,18 +142,18 @@ if (LL_TESTS)
|
|||
# If http_proxy is in the current environment (e.g. to fetch s3-proxy
|
||||
# autobuild packages), suppress it for this integration test: it screws up
|
||||
# the tests.
|
||||
#LL_ADD_INTEGRATION_TEST(llcorehttp
|
||||
# "${llcorehttp_TEST_SOURCE_FILES}"
|
||||
# "${test_libs}"
|
||||
# "-Dhttp_proxy"
|
||||
# ${PYTHON_EXECUTABLE}
|
||||
# "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llcorehttp_peer.py"
|
||||
# )
|
||||
LL_ADD_INTEGRATION_TEST(llcorehttp
|
||||
"${llcorehttp_TEST_SOURCE_FILES}"
|
||||
"${test_libs}"
|
||||
"-Dhttp_proxy"
|
||||
${PYTHON_EXECUTABLE}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llcorehttp_peer.py"
|
||||
)
|
||||
|
||||
if (DARWIN)
|
||||
# Path inside the app bundle where we'll need to copy libraries
|
||||
set(LL_TEST_DESTINATION_DIR
|
||||
${CMAKE_SOURCE_DIR}/../build-darwin-i386/sharedlibs/Resources
|
||||
${CMAKE_BINARY_DIR}/sharedlibs/Resources
|
||||
)
|
||||
|
||||
# Create the Contents/Resources directory
|
||||
|
|
@ -164,21 +169,23 @@ if (DARWIN)
|
|||
|
||||
# Copy the required libraries to the package app
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libapr-1.0.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libaprutil-1.0.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexception_handler.dylib
|
||||
)
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../build-darwin-i386/packages/lib/release/libexpat.1.5.2.dylib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib
|
||||
)
|
||||
foreach(expat ${EXPAT_COPY})
|
||||
add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat} ${LL_TEST_DESTINATION_DIR}
|
||||
DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat}
|
||||
)
|
||||
endforeach(expat)
|
||||
|
||||
endif (DARWIN)
|
||||
|
||||
|
|
@ -198,6 +205,7 @@ endif (DARWIN)
|
|||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARIES}
|
||||
${NGHTTP2_LIBRARIES}
|
||||
${BOOST_THREAD_LIBRARY}
|
||||
${BOOST_SYSTEM_LIBRARY}
|
||||
)
|
||||
|
|
@ -214,7 +222,7 @@ endif (DARWIN)
|
|||
# The following come from LLAddBuildTest.cmake's INTEGRATION_TEST_xxxx target.
|
||||
set_target_properties(http_texture_load
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:CONSOLE ${TCMALLOC_LINK_FLAGS}"
|
||||
LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:CONSOLE"
|
||||
LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO"
|
||||
LINK_FLAGS_RELEASE ""
|
||||
)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,15 @@ namespace
|
|||
void check_curl_multi_code(CURLMcode code);
|
||||
void check_curl_multi_code(CURLMcode code, int curl_setopt_option);
|
||||
|
||||
// This is a template because different 'option' values require different
|
||||
// types for 'ARG'. Just pass them through unchanged (by value).
|
||||
template <typename ARG>
|
||||
void check_curl_multi_setopt(CURLM* handle, CURLMoption option, ARG argument)
|
||||
{
|
||||
CURLMcode code = curl_multi_setopt(handle, option, argument);
|
||||
check_curl_multi_code(code, option);
|
||||
}
|
||||
|
||||
static const char * const LOG_CORE("CoreHttp");
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
@ -461,46 +470,38 @@ void HttpLibcurl::policyUpdated(int policy_class)
|
|||
|
||||
HttpPolicyClass & options(policy.getClassOptions(policy_class));
|
||||
CURLM * multi_handle(mMultiHandles[policy_class]);
|
||||
CURLMcode code;
|
||||
|
||||
// Enable policy if stalled
|
||||
policy.stallPolicy(policy_class, false);
|
||||
mDirtyPolicy[policy_class] = false;
|
||||
|
||||
|
||||
if (options.mPipelining > 1)
|
||||
{
|
||||
// We'll try to do pipelining on this multihandle
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_PIPELINING,
|
||||
1L);
|
||||
check_curl_multi_code(code, CURLMOPT_PIPELINING);
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_MAX_PIPELINE_LENGTH,
|
||||
long(options.mPipelining));
|
||||
check_curl_multi_code(code, CURLMOPT_MAX_PIPELINE_LENGTH);
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_MAX_HOST_CONNECTIONS,
|
||||
long(options.mPerHostConnectionLimit));
|
||||
check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS);
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_MAX_TOTAL_CONNECTIONS,
|
||||
long(options.mConnectionLimit));
|
||||
check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);
|
||||
}
|
||||
else
|
||||
{
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_PIPELINING,
|
||||
0L);
|
||||
check_curl_multi_code(code, CURLMOPT_PIPELINING);
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_MAX_HOST_CONNECTIONS,
|
||||
0L);
|
||||
check_curl_multi_code(code, CURLMOPT_MAX_HOST_CONNECTIONS);
|
||||
code = curl_multi_setopt(multi_handle,
|
||||
check_curl_multi_setopt(multi_handle,
|
||||
CURLMOPT_MAX_TOTAL_CONNECTIONS,
|
||||
long(options.mConnectionLimit));
|
||||
check_curl_multi_code(code, CURLMOPT_MAX_TOTAL_CONNECTIONS);
|
||||
}
|
||||
}
|
||||
else if (! mDirtyPolicy[policy_class])
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#include "llhttpconstants.h"
|
||||
#include "llproxy.h"
|
||||
|
||||
#include "httpstats.h"
|
||||
|
||||
// *DEBUG: "[curl:bugs] #1420" problem and testing.
|
||||
//
|
||||
// A pipelining problem, https://sourceforge.net/p/curl/bugs/1420/,
|
||||
|
|
@ -106,6 +108,15 @@ void os_strlower(char * str);
|
|||
// Error testing and reporting for libcurl status codes
|
||||
void check_curl_easy_code(CURLcode code, int curl_setopt_option);
|
||||
|
||||
// This is a template because different 'option' values require different
|
||||
// types for 'ARG'. Just pass them through unchanged (by value).
|
||||
template <typename ARG>
|
||||
void check_curl_easy_setopt(CURL* handle, CURLoption option, ARG argument)
|
||||
{
|
||||
CURLcode code = curl_easy_setopt(handle, option, argument);
|
||||
check_curl_easy_code(code, option);
|
||||
}
|
||||
|
||||
static const char * const LOG_CORE("CoreHttp");
|
||||
|
||||
} // end anonymous namespace
|
||||
|
|
@ -247,6 +258,8 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
|
|||
response->setHeaders(mReplyHeaders);
|
||||
response->setRequestURL(mReqURL);
|
||||
|
||||
response->setRequestMethod(methodToString(mReqMethod));
|
||||
|
||||
if (mReplyOffset || mReplyLength)
|
||||
{
|
||||
// Got an explicit offset/length in response
|
||||
|
|
@ -452,8 +465,6 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,
|
|||
// *TODO: Move this to _httplibcurl where it belongs.
|
||||
HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
||||
{
|
||||
CURLcode code;
|
||||
|
||||
// Scrub transport and result data for retried op case
|
||||
mCurlActive = false;
|
||||
mCurlHandle = NULL;
|
||||
|
|
@ -492,45 +503,28 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC);
|
||||
}
|
||||
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
check_curl_easy_code(code, CURLOPT_IPRESOLVE);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
|
||||
check_curl_easy_code(code, CURLOPT_NOSIGNAL);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
|
||||
check_curl_easy_code(code, CURLOPT_NOPROGRESS);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
|
||||
check_curl_easy_code(code, CURLOPT_URL);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
|
||||
check_curl_easy_code(code, CURLOPT_PRIVATE);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
check_curl_easy_code(code, CURLOPT_ENCODING);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
|
||||
check_curl_easy_code(code, CURLOPT_AUTOREFERER);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
|
||||
check_curl_easy_code(code, CURLOPT_MAXREDIRS);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
|
||||
check_curl_easy_code(code, CURLOPT_WRITEFUNCTION);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle());
|
||||
check_curl_easy_code(code, CURLOPT_WRITEDATA);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
|
||||
check_curl_easy_code(code, CURLOPT_READFUNCTION);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle());
|
||||
check_curl_easy_code(code, CURLOPT_READDATA);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback);
|
||||
check_curl_easy_code(code, CURLOPT_SEEKFUNCTION);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle());
|
||||
check_curl_easy_code(code, CURLOPT_SEEKDATA);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, getHandle());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, getHandle());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKFUNCTION, seekCallback);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SEEKDATA, getHandle());
|
||||
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, "");
|
||||
check_curl_easy_code(code, CURLOPT_COOKIEFILE);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_COOKIEFILE, "");
|
||||
|
||||
if (gpolicy.mSslCtxCallback)
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback);
|
||||
check_curl_easy_code(code, CURLOPT_SSL_CTX_FUNCTION);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle());
|
||||
check_curl_easy_code(code, CURLOPT_SSL_CTX_DATA);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_FUNCTION, curlSslCtxCallback);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_CTX_DATA, getHandle());
|
||||
mCallbackSSLVerify = gpolicy.mSslCtxCallback;
|
||||
}
|
||||
|
||||
|
|
@ -548,16 +542,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
|
||||
nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
|
||||
}
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
|
||||
check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
|
||||
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV);
|
||||
check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);
|
||||
check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, sslPeerV);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);
|
||||
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
|
||||
check_curl_easy_code(code, CURLOPT_NOBODY);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
|
||||
|
||||
// The Linksys WRT54G V5 router has an issue with frequent
|
||||
// DNS lookups from LAN machines. If they happen too often,
|
||||
|
|
@ -565,8 +555,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
// about 700 or so requests and starts issuing TCP RSTs to
|
||||
// new connections. Reuse the DNS lookups for even a few
|
||||
// seconds and no RSTs.
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
|
||||
check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
|
||||
|
||||
if (gpolicy.mUseLLProxy)
|
||||
{
|
||||
|
|
@ -589,81 +578,66 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
{
|
||||
// *TODO: This is fine for now but get fuller socks5/
|
||||
// authentication thing going later....
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str());
|
||||
check_curl_easy_code(code, CURLOPT_PROXY);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
check_curl_easy_code(code, CURLOPT_PROXYTYPE);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, gpolicy.mHttpProxy.c_str());
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
}
|
||||
if (gpolicy.mCAPath.size())
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str());
|
||||
check_curl_easy_code(code, CURLOPT_CAPATH);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, gpolicy.mCAPath.c_str());
|
||||
}
|
||||
if (gpolicy.mCAFile.size())
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str());
|
||||
check_curl_easy_code(code, CURLOPT_CAINFO);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, gpolicy.mCAFile.c_str());
|
||||
}
|
||||
|
||||
switch (mReqMethod)
|
||||
{
|
||||
case HOR_GET:
|
||||
if (nobody == 0)
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
|
||||
check_curl_easy_code(code, CURLOPT_HTTPGET);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
|
||||
break;
|
||||
|
||||
case HOR_POST:
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
|
||||
check_curl_easy_code(code, CURLOPT_POST);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
check_curl_easy_code(code, CURLOPT_ENCODING);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
long data_size(0);
|
||||
if (mReqBody)
|
||||
{
|
||||
data_size = mReqBody->size();
|
||||
}
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
|
||||
check_curl_easy_code(code, CURLOPT_POSTFIELDS);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
|
||||
check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
|
||||
}
|
||||
break;
|
||||
|
||||
case HOR_PATCH:
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
// fall through. The rest is the same as PUT
|
||||
case HOR_PUT:
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
|
||||
check_curl_easy_code(code, CURLOPT_UPLOAD);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
|
||||
long data_size(0);
|
||||
if (mReqBody)
|
||||
{
|
||||
data_size = mReqBody->size();
|
||||
}
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
|
||||
check_curl_easy_code(code, CURLOPT_INFILESIZE);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
|
||||
}
|
||||
break;
|
||||
|
||||
case HOR_DELETE:
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
break;
|
||||
|
||||
case HOR_COPY:
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY");
|
||||
check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "COPY");
|
||||
break;
|
||||
|
||||
case HOR_MOVE:
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE");
|
||||
check_curl_easy_code(code, CURLOPT_CUSTOMREQUEST);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CUSTOMREQUEST, "MOVE");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -681,12 +655,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
// Tracing
|
||||
if (mTracing >= HTTP_TRACE_CURL_HEADERS)
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
|
||||
check_curl_easy_code(code, CURLOPT_VERBOSE);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
|
||||
check_curl_easy_code(code, CURLOPT_DEBUGDATA);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
|
||||
check_curl_easy_code(code, CURLOPT_DEBUGFUNCTION);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
|
||||
}
|
||||
|
||||
// There's a CURLOPT for this now...
|
||||
|
|
@ -763,6 +734,13 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
//
|
||||
// xfer_timeout *= cpolicy.mPipelining;
|
||||
xfer_timeout *= 2L;
|
||||
|
||||
// Also try requesting HTTP/2.
|
||||
/******************************/
|
||||
// but for test purposes, only if overriding VIEWERASSET
|
||||
if (getenv("VIEWERASSET"))
|
||||
/******************************/
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
|
||||
}
|
||||
// *DEBUG: Enable following override for timeout handling and "[curl:bugs] #1420" tests
|
||||
//if (cpolicy.mPipelining)
|
||||
|
|
@ -770,10 +748,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
// xfer_timeout = 1L;
|
||||
// timeout = 1L;
|
||||
//}
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
|
||||
check_curl_easy_code(code, CURLOPT_TIMEOUT);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||
check_curl_easy_code(code, CURLOPT_CONNECTTIMEOUT);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||
|
||||
// Request headers
|
||||
if (mReqHeaders)
|
||||
|
|
@ -781,15 +757,12 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
// Caller's headers last to override
|
||||
mCurlHeaders = append_headers_to_slist(mReqHeaders, mCurlHeaders);
|
||||
}
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
|
||||
check_curl_easy_code(code, CURLOPT_HTTPHEADER);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
|
||||
|
||||
if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_USE_RETRY_AFTER))
|
||||
{
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
|
||||
check_curl_easy_code(code, CURLOPT_HEADERFUNCTION);
|
||||
code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
|
||||
check_curl_easy_code(code, CURLOPT_HEADERDATA);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
|
||||
}
|
||||
|
||||
if (status)
|
||||
|
|
@ -810,6 +783,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void
|
|||
}
|
||||
const size_t req_size(size * nmemb);
|
||||
const size_t write_size(op->mReplyBody->append(static_cast<char *>(data), req_size));
|
||||
HTTPStats::instance().recordDataDown(write_size);
|
||||
return write_size;
|
||||
}
|
||||
|
||||
|
|
@ -838,7 +812,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
|
|||
|
||||
const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos));
|
||||
const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size));
|
||||
op->mCurlBodyPos += read_size;
|
||||
HTTPStats::instance().recordDataUp(read_size);
|
||||
op->mCurlBodyPos += read_size;
|
||||
return read_size;
|
||||
}
|
||||
|
||||
|
|
@ -1143,6 +1118,25 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::string HttpOpRequest::methodToString(const HttpOpRequest::EMethod &e)
|
||||
{
|
||||
if (e == HOR_COPY)
|
||||
return "COPY";
|
||||
else if (e == HOR_DELETE)
|
||||
return "DELETE";
|
||||
else if (e == HOR_GET)
|
||||
return "GET";
|
||||
else if (e == HOR_MOVE)
|
||||
return "MOVE";
|
||||
else if (e == HOR_PATCH)
|
||||
return "PATCH";
|
||||
else if (e == HOR_POST)
|
||||
return "POST";
|
||||
else if (e == HOR_PUT)
|
||||
return "PUT";
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
} // end namespace LLCore
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ public:
|
|||
HOR_COPY,
|
||||
HOR_MOVE
|
||||
};
|
||||
|
||||
static std::string methodToString(const EMethod &);
|
||||
|
||||
virtual void stageFromRequest(HttpService *);
|
||||
virtual void stageFromReady(HttpService *);
|
||||
virtual void stageFromActive(HttpService *);
|
||||
|
|
@ -237,6 +238,7 @@ public:
|
|||
}; // end class HttpOpRequest
|
||||
|
||||
|
||||
|
||||
/// HttpOpRequestCompare isn't an operation but a uniform comparison
|
||||
/// functor for STL containers that order by priority. Mainly
|
||||
/// used for the ready queue container but defined here.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "_httppolicyclass.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "httpstats.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -444,6 +445,8 @@ bool HttpPolicy::stageAfterCompletion(const HttpOpRequest::ptr_t &op)
|
|||
}
|
||||
|
||||
op->stageFromActive(mService);
|
||||
|
||||
HTTPStats::instance().recordResultCode(op->mStatus.getType());
|
||||
return false; // not active
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
|
||||
#include "lltimer.h"
|
||||
#include "llthread.h"
|
||||
|
||||
#include "llexception.h"
|
||||
#include "llmemory.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -293,22 +294,42 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
|
|||
ELoopSpeed loop(REQUEST_SLEEP);
|
||||
while (! mExitRequested)
|
||||
{
|
||||
loop = processRequestQueue(loop);
|
||||
try
|
||||
{
|
||||
loop = processRequestQueue(loop);
|
||||
|
||||
// Process ready queue issuing new requests as needed
|
||||
ELoopSpeed new_loop = mPolicy->processReadyQueue();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
// Process ready queue issuing new requests as needed
|
||||
ELoopSpeed new_loop = mPolicy->processReadyQueue();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
|
||||
// Give libcurl some cycles
|
||||
new_loop = mTransport->processTransport();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
// Give libcurl some cycles
|
||||
new_loop = mTransport->processTransport();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
|
||||
// Determine whether to spin, sleep briefly or sleep for next request
|
||||
if (REQUEST_SLEEP != loop)
|
||||
{
|
||||
ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS);
|
||||
}
|
||||
}
|
||||
// Determine whether to spin, sleep briefly or sleep for next request
|
||||
if (REQUEST_SLEEP != loop)
|
||||
{
|
||||
ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS);
|
||||
}
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_ERRS() << "Bad memory allocation in HttpService::threadRun()!" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
}
|
||||
|
||||
shutdown();
|
||||
sState = STOPPED;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
*/
|
||||
|
||||
#include "bufferarray.h"
|
||||
#include "llexception.h"
|
||||
#include "llmemory.h"
|
||||
|
||||
|
||||
// BufferArray is a list of chunks, each a BufferArray::Block, of contiguous
|
||||
|
|
@ -140,8 +142,22 @@ size_t BufferArray::append(const void * src, size_t len)
|
|||
{
|
||||
mBlocks.reserve(mBlocks.size() + 5);
|
||||
}
|
||||
Block * block = Block::alloc(BLOCK_ALLOC_SIZE);
|
||||
memcpy(block->mData, c_src, copy_len);
|
||||
Block * block;
|
||||
try
|
||||
{
|
||||
block = Block::alloc(BLOCK_ALLOC_SIZE);
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_WARNS() << "Bad memory allocation in thrown by Block::alloc in read!" << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
memcpy(block->mData, c_src, copy_len);
|
||||
block->mUsed = copy_len;
|
||||
llassert_always(block->mUsed <= block->mAlloced);
|
||||
mBlocks.push_back(block);
|
||||
|
|
@ -149,7 +165,7 @@ size_t BufferArray::append(const void * src, size_t len)
|
|||
c_src += copy_len;
|
||||
len -= copy_len;
|
||||
}
|
||||
return ret;
|
||||
return ret - len;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ HttpStatus::type_enum_t EXT_CURL_EASY;
|
|||
HttpStatus::type_enum_t EXT_CURL_MULTI;
|
||||
HttpStatus::type_enum_t LLCORE;
|
||||
|
||||
HttpStatus::operator unsigned long() const
|
||||
HttpStatus::operator U32() const
|
||||
{
|
||||
static const int shift(sizeof(unsigned long) * 4);
|
||||
// Effectively, concatenate mType (high) with mStatus (low).
|
||||
static const int shift(sizeof(mDetails->mStatus) * 8);
|
||||
|
||||
unsigned long result(((unsigned long)mDetails->mType) << shift | (unsigned long)(int)mDetails->mStatus);
|
||||
U32 result(U32(mDetails->mType) << shift | U32((int)mDetails->mStatus));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ std::string HttpStatus::toHex() const
|
|||
std::ostringstream result;
|
||||
result.width(8);
|
||||
result.fill('0');
|
||||
result << std::hex << operator unsigned long();
|
||||
result << std::hex << operator U32();
|
||||
return result.str();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -383,10 +383,10 @@ struct HttpStatus
|
|||
/// creates an ambiguous second path to integer conversion
|
||||
/// which tends to find programming errors such as formatting
|
||||
/// the status to a stream (operator<<).
|
||||
operator unsigned long() const;
|
||||
unsigned long toULong() const
|
||||
operator U32() const;
|
||||
U32 toULong() const
|
||||
{
|
||||
return operator unsigned long();
|
||||
return operator U32();
|
||||
}
|
||||
|
||||
/// And to convert to a hex string.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "_httpopsetget.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
|
||||
#include "httpstats.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -62,6 +62,8 @@ HttpRequest::HttpRequest()
|
|||
mRequestQueue->addRef();
|
||||
|
||||
mReplyQueue.reset( new HttpReplyQueue() );
|
||||
|
||||
HTTPStats::instance().recordHTTPRequest();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ private:
|
|||
/// @}
|
||||
// End Global State
|
||||
// ====================================
|
||||
|
||||
|
||||
}; // end class HttpRequest
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,15 @@ public:
|
|||
return mRequestUrl;
|
||||
}
|
||||
|
||||
void setRequestMethod(const std::string &method)
|
||||
{
|
||||
mRequestMethod = method;
|
||||
}
|
||||
|
||||
const std::string &getRequestMethod() const
|
||||
{
|
||||
return mRequestMethod;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Response data here
|
||||
|
|
@ -217,6 +226,7 @@ protected:
|
|||
unsigned int mRetries;
|
||||
unsigned int m503Retries;
|
||||
std::string mRequestUrl;
|
||||
std::string mRequestMethod;
|
||||
|
||||
TransferStats::ptr_t mStats;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* @file llviewerstats.cpp
|
||||
* @brief LLViewerStats class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "httpstats.h"
|
||||
#include "llerror.h"
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
HTTPStats::HTTPStats()
|
||||
{
|
||||
resetStats();
|
||||
}
|
||||
|
||||
|
||||
HTTPStats::~HTTPStats()
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPStats::resetStats()
|
||||
{
|
||||
mResutCodes.clear();
|
||||
mDataDown.reset();
|
||||
mDataUp.reset();
|
||||
mRequests = 0;
|
||||
}
|
||||
|
||||
|
||||
void HTTPStats::recordResultCode(S32 code)
|
||||
{
|
||||
std::map<S32, S32>::iterator it;
|
||||
|
||||
it = mResutCodes.find(code);
|
||||
|
||||
if (it == mResutCodes.end())
|
||||
mResutCodes[code] = 1;
|
||||
else
|
||||
(*it).second = (*it).second + 1;
|
||||
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string byte_count_converter(F32 bytes)
|
||||
{
|
||||
static const char unit_suffix[] = { 'B', 'K', 'M', 'G' };
|
||||
|
||||
F32 value = bytes;
|
||||
int suffix = 0;
|
||||
|
||||
while ((value > 1024.0) && (suffix < 3))
|
||||
{
|
||||
value /= 1024.0;
|
||||
++suffix;
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
out << std::setprecision(4) << value << unit_suffix[suffix];
|
||||
|
||||
return out.str();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPStats::dumpStats()
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
out << "HTTP DATA SUMMARY" << std::endl;
|
||||
out << "HTTP Transfer counts:" << std::endl;
|
||||
out << "Data Sent: " << byte_count_converter(mDataUp.getSum()) << " (" << mDataUp.getSum() << ")" << std::endl;
|
||||
out << "Data Recv: " << byte_count_converter(mDataDown.getSum()) << " (" << mDataDown.getSum() << ")" << std::endl;
|
||||
out << "Total requests: " << mRequests << "(request objects created)" << std::endl;
|
||||
out << std::endl;
|
||||
out << "Result Codes:" << std::endl << "--- -----" << std::endl;
|
||||
|
||||
for (std::map<S32, S32>::iterator it = mResutCodes.begin(); it != mResutCodes.end(); ++it)
|
||||
{
|
||||
out << (*it).first << " " << (*it).second << std::endl;
|
||||
}
|
||||
|
||||
LL_WARNS("HTTP Core") << out.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file llviewerim_peningtats.h
|
||||
* @brief LLViewerStats class header file
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLVIEWERSTATS_H
|
||||
#define LL_LLVIEWERSTATS_H
|
||||
|
||||
#include "lltracerecording.h"
|
||||
#include "lltrace.h"
|
||||
#include "llstatsaccumulator.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llsd.h"
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
class HTTPStats : public LLSingleton<HTTPStats>
|
||||
{
|
||||
LLSINGLETON(HTTPStats);
|
||||
virtual ~HTTPStats();
|
||||
|
||||
public:
|
||||
void resetStats();
|
||||
|
||||
typedef LLStatsAccumulator StatsAccumulator;
|
||||
|
||||
void recordDataDown(size_t bytes)
|
||||
{
|
||||
mDataDown.push(bytes);
|
||||
}
|
||||
|
||||
void recordDataUp(size_t bytes)
|
||||
{
|
||||
mDataUp.push(bytes);
|
||||
}
|
||||
|
||||
void recordHTTPRequest() { ++mRequests; }
|
||||
|
||||
void recordResultCode(S32 code);
|
||||
|
||||
void dumpStats();
|
||||
private:
|
||||
StatsAccumulator mDataDown;
|
||||
StatsAccumulator mDataUp;
|
||||
|
||||
S32 mRequests;
|
||||
|
||||
std::map<S32, S32> mResutCodes;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif // LL_LLVIEWERSTATS_H
|
||||
|
|
@ -215,7 +215,8 @@ void HttpRequestTestObjectType::test<1>()
|
|||
HttpRequest::destroyService();
|
||||
|
||||
// make sure we didn't leak any memory
|
||||
ensure("Memory returned", mMemTotal == GetMemTotal());
|
||||
// nat 2017-08-15 don't: requires total stasis in every other subsystem
|
||||
// ensure("Memory returned", mMemTotal == GetMemTotal());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
@ -835,7 +836,7 @@ void HttpRequestTestObjectType::test<8>()
|
|||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if 0 // defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
|
@ -946,7 +947,7 @@ void HttpRequestTestObjectType::test<9>()
|
|||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if 0 // defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
|
@ -1182,7 +1183,7 @@ void HttpRequestTestObjectType::test<11>()
|
|||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if 0 // defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
|
@ -1428,7 +1429,7 @@ void HttpRequestTestObjectType::test<13>()
|
|||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if 0 // defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
|
@ -1662,7 +1663,7 @@ void HttpRequestTestObjectType::test<15>()
|
|||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
#if 0 // defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
|
@ -3089,6 +3090,10 @@ void HttpRequestTestObjectType::test<23>()
|
|||
|
||||
set_test_name("HttpRequest GET 503s with 'Retry-After'");
|
||||
|
||||
#if LL_WINDOWS && ADDRESS_SIZE == 64
|
||||
skip("llcorehttp 503-with-retry test hangs on Windows 64");
|
||||
#endif
|
||||
|
||||
// This tests mainly that the code doesn't fall over if
|
||||
// various well- and mis-formed Retry-After headers are
|
||||
// sent along with the response. Direct inspection of
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ void HttpStatusTestObjectType::test<7>()
|
|||
HttpStatus status(404);
|
||||
std::string msg = status.toHex();
|
||||
// std::cout << "Result: " << msg << std::endl;
|
||||
ensure(msg == "01940001");
|
||||
ensure_equals(msg, "01940001");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1227,9 +1227,10 @@ void LLImageRaw::fill( const LLColor4U& color )
|
|||
if( 4 == getComponents() )
|
||||
{
|
||||
U32* data = (U32*) getData();
|
||||
U32 rgbaColor = color.asRGBA();
|
||||
for( S32 i = 0; i < pixels; i++ )
|
||||
{
|
||||
data[i] = color.mAll;
|
||||
data[ i ] = rgbaColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -811,7 +811,7 @@ bool LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, bool &alpha_opaque
|
|||
}
|
||||
|
||||
src += 4;
|
||||
register U32 value = rgba;
|
||||
U32 value = rgba;
|
||||
do
|
||||
{
|
||||
*dst_pixels = value;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,12 @@ LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
|
|||
|
||||
std::string LLImageJ2COJ::getEngineInfo() const
|
||||
{
|
||||
#ifdef OPENJPEG_VERSION
|
||||
return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
|
||||
+ opj_version();
|
||||
#else
|
||||
return std::string("OpenJPEG runtime: ") + opj_version();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return string from message, eliminating final \n if present
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ set_source_files_properties(${llkdu_HEADER_FILES}
|
|||
|
||||
list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
|
||||
|
||||
# Our KDU package is built with KDU_X86_INTRINSICS in its .vcxproj file.
|
||||
# Unless that macro is also set for every consumer build, KDU freaks out,
|
||||
# spamming the viewer log with alignment FUD.
|
||||
set_source_files_properties(${llkdu_SOURCE_FILES}
|
||||
PROPERTIES
|
||||
COMPILE_DEFINITIONS
|
||||
"KDU_X86_INTRINSICS")
|
||||
|
||||
if (USE_KDU)
|
||||
add_library (llkdu ${llkdu_SOURCE_FILES})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* @file include_kdu_xxxx.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2016-04-25
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Copyright (c) 2016, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// This file specifically omits #include guards of its own: it's sort of an
|
||||
// #include macro used to wrap KDU #includes with proper incantations. Usage:
|
||||
|
||||
// #define kdu_xxxx "kdu_compressed.h" // or whichever KDU header
|
||||
// #include "include_kdu_xxxx.h"
|
||||
// // kdu_xxxx #undef'ed by include_kdu_xxxx.h
|
||||
|
||||
#if LL_DARWIN
|
||||
// don't *really* want to rebuild KDU so turn off specific warnings for this header
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wself-assign-field"
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#include kdu_xxxx
|
||||
#pragma clang diagnostic pop
|
||||
#elif LL_WINDOWS
|
||||
// With warnings-as-errors in effect, strange relationship between
|
||||
// jp2_output_box and its subclass jp2_target in kdu_compressed.h
|
||||
// causes build failures. Specifically:
|
||||
// warning C4263: 'void kdu_supp::jp2_target::open(kdu_supp::jp2_family_tgt *)' : member function does not override any base class virtual member function
|
||||
// warning C4264: 'void kdu_supp::jp2_output_box::open(kdu_core::kdu_uint32)' : no override available for virtual member function from base 'kdu_supp::jp2_output_box'; function is hidden
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4263 4264)
|
||||
#include kdu_xxxx
|
||||
#pragma warning(pop)
|
||||
#else // some other platform
|
||||
#include kdu_xxxx
|
||||
#endif
|
||||
|
||||
#undef kdu_xxxx
|
||||
|
|
@ -25,21 +25,37 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llimagej2ckdu.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "llpointer.h"
|
||||
#include "llmath.h"
|
||||
#include "llkdumem.h"
|
||||
#include "stringize.h"
|
||||
|
||||
#include "kdu_block_coding.h"
|
||||
#define kdu_xxxx "kdu_block_coding.h"
|
||||
#include "include_kdu_xxxx.h"
|
||||
|
||||
// Avoid ubiquitous necessity of kdu_core:: qualification
|
||||
using namespace kdu_core;
|
||||
|
||||
#include "llexception.h"
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
// stream kdu_dims to std::ostream
|
||||
// Turns out this must NOT be in the anonymous namespace!
|
||||
// It must also precede #include "stringize.h".
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
|
||||
{
|
||||
return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
|
||||
"[" << dims.size.x << "x" << dims.size.y << "]";
|
||||
}
|
||||
|
||||
#include "stringize.h"
|
||||
|
||||
namespace {
|
||||
// Failure to load an image shouldn't crash the whole viewer.
|
||||
struct KDUError: public LLContinueError
|
||||
|
|
@ -82,20 +98,11 @@ std::string report_kdu_exception(kdu_exception mb)
|
|||
}
|
||||
} // anonymous namespace
|
||||
|
||||
// stream kdu_dims to std::ostream
|
||||
// Turns out this must NOT be in the anonymous namespace!
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
|
||||
{
|
||||
return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
|
||||
"[" << dims.size.x << "x" << dims.size.y << "]";
|
||||
}
|
||||
|
||||
|
||||
class kdc_flow_control {
|
||||
|
||||
public:
|
||||
kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream);
|
||||
kdc_flow_control(kdu_supp::kdu_image_in_base *img_in, kdu_codestream codestream);
|
||||
~kdc_flow_control();
|
||||
bool advance_components();
|
||||
void process_components();
|
||||
|
|
@ -104,7 +111,7 @@ private:
|
|||
|
||||
struct kdc_component_flow_control {
|
||||
public:
|
||||
kdu_image_in_base *reader;
|
||||
kdu_supp::kdu_image_in_base *reader;
|
||||
int vert_subsampling;
|
||||
int ratio_counter; /* Initialized to 0, decremented by `count_delta';
|
||||
when < 0, a new line must be processed, after
|
||||
|
|
@ -144,7 +151,8 @@ std::string LLImageJ2CKDU::getEngineInfo() const
|
|||
class LLKDUDecodeState
|
||||
{
|
||||
public:
|
||||
LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap);
|
||||
LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
|
||||
kdu_codestream* codestreamp);
|
||||
~LLKDUDecodeState();
|
||||
bool processTileDecode(F32 decode_time, bool limit_time = true);
|
||||
|
||||
|
|
@ -346,9 +354,9 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
|
|||
// This method is only called from methods that catch KDUError.
|
||||
// We want to fail the image load, not crash the viewer.
|
||||
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
<< other_dims
|
||||
<< " do not match component 0 dimensions "
|
||||
<< dims << "!")));
|
||||
<< stringize(other_dims)
|
||||
<< " do not match component 0 dimensions "
|
||||
<< stringize(dims) << "!")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -560,7 +568,8 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
kdu_coords offset = tile_dims.pos - dims.pos;
|
||||
int row_gap = channels*dims.size.x; // inter-row separation
|
||||
kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels;
|
||||
mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap));
|
||||
mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap,
|
||||
mCodeStreamp.get()));
|
||||
}
|
||||
// Do the actual processing
|
||||
F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32();
|
||||
|
|
@ -1248,7 +1257,8 @@ all necessary level shifting, type conversion, rounding and truncation. */
|
|||
}
|
||||
}
|
||||
|
||||
LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
|
||||
LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
|
||||
kdu_codestream* codestreamp)
|
||||
{
|
||||
S32 c;
|
||||
|
||||
|
|
@ -1294,7 +1304,7 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
|
|||
mEngines[c] = kdu_synthesis(res,&mAllocator,use_shorts);
|
||||
}
|
||||
}
|
||||
mAllocator.finalize(); // Actually creates buffering resources
|
||||
mAllocator.finalize(*codestreamp); // Actually creates buffering resources
|
||||
for (c = 0; c < mNumComponents; c++)
|
||||
{
|
||||
mLines[c].create(); // Grabs resources from the allocator.
|
||||
|
|
@ -1352,7 +1362,7 @@ separation between consecutive rows in the real buffer. */
|
|||
|
||||
// kdc_flow_control
|
||||
|
||||
kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream)
|
||||
kdc_flow_control::kdc_flow_control (kdu_supp::kdu_image_in_base *img_in, kdu_codestream codestream)
|
||||
{
|
||||
int n;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue