blob: c27b3b2c649ba1a27f02392ceaae5b0f681b2809 [file] [log] [blame]
#!/usr/bin/env perl
use strict;
use warnings;
use File::Path qw(make_path);
use File::Spec;
use File::Basename;
use Cwd 'abs_path';
use Win32;
# Copyright (C) 2007, 2009, 2014 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
sub splitVersion($);
die "You must supply an output path as the argument.\n" if ($#ARGV < 0);
my $rawPath = $0;
if ($^O eq "cygwin") {
chomp($rawPath = `/usr/bin/cygpath -u "$0"`);
}
my $thisDirectory = dirname(abs_path($rawPath));
my $FALLBACK_VERSION_PATH = File::Spec->catfile($thisDirectory, 'VERSION');
open(FALLBACK_VERSION_FILE, '<', $FALLBACK_VERSION_PATH) or die "Unable to open $FALLBACK_VERSION_PATH: $!";
my $FALLBACK_VERSION = <FALLBACK_VERSION_FILE>;
close FALLBACK_VERSION_FILE;
chomp($FALLBACK_VERSION);
my $COPYRIGHT_END_YEAR_PATH = File::Spec->catfile($thisDirectory, 'COPYRIGHT-END-YEAR');
open(COPYRIGHT_END_YEAR_FILE, '<', $COPYRIGHT_END_YEAR_PATH) or die "Unable to open $COPYRIGHT_END_YEAR_PATH: $!";
my $COPYRIGHT_END_YEAR = <COPYRIGHT_END_YEAR_FILE>;
close COPYRIGHT_END_YEAR_FILE;
chomp($COPYRIGHT_END_YEAR);
# Make sure we don't have any leading or trailing quote
$ARGV[0] =~ s/^\"//;
$ARGV[0] =~ s/\"$//;
my $OUTPUT_DIR = File::Spec->catdir(File::Spec->canonpath($ARGV[0]), 'include');
unless (-d $OUTPUT_DIR) {
make_path($OUTPUT_DIR) or die "Couldn't create $OUTPUT_DIR: $!";
}
my $OUTPUT_FILE = File::Spec->catfile($OUTPUT_DIR, 'autoversion.h');
# Take the initial version number from RC_ProjectSourceVersion if it
# exists, otherwise fall back to the version number stored in the source.
my $ENVIRONMENT_VERSION = $ENV{'RC_ProjectSourceVersion'} || $ENV{'RC_PROJECTSOURCEVERSION'};
my $PROPOSED_VERSION = $ENVIRONMENT_VERSION || $FALLBACK_VERSION;
chomp($PROPOSED_VERSION);
my ($BUILD_MAJOR_VERSION, $BUILD_MINOR_VERSION, $BUILD_TINY_VERSION, $BUILD_VARIANT_VERSION, $ADJUSTED_PROPOSED_VERSION, $FULL_BUILD_MAJOR_VERSION) = splitVersion($PROPOSED_VERSION);
my $TINY_VERSION = $BUILD_TINY_VERSION;
my $VERSION_TEXT = $ADJUSTED_PROPOSED_VERSION;
my $VERSION_TEXT_SHORT = $VERSION_TEXT;
my $SVN_REVISION = '';
if (!$ENVIRONMENT_VERSION) {
# If we didn't pull the version number from the environment then we're doing
# an engineering build and we'll stamp the build with some more information.
my $BUILD_DATE = localtime(time);
my $SVN_REVISION = `svn info`;
$SVN_REVISION =~ m/Revision: (\d+)/;
$SVN_REVISION= $1;
chomp($BUILD_DATE);
chomp($SVN_REVISION);
$VERSION_TEXT_SHORT .= "+";
my $USER = Win32::LoginName;
$VERSION_TEXT = "$VERSION_TEXT_SHORT $USER - $BUILD_DATE - r$SVN_REVISION";
}
open(OUTPUT_FILE, '>', $OUTPUT_FILE) or die "Couldn't open $OUTPUT_FILE: $!";
print OUTPUT_FILE <<EOF;
#define __VERSION_TEXT__ "$VERSION_TEXT"
#define __BUILD_NUMBER__ "$VERSION_TEXT"
#define __BUILD_NUMBER_SHORT__ "$VERSION_TEXT_SHORT"
#define __VERSION_MAJOR__ $BUILD_MAJOR_VERSION
#define __VERSION_MINOR__ $BUILD_MINOR_VERSION
#define __VERSION_TINY__ $BUILD_TINY_VERSION
#define __VERSION_BUILD__ $BUILD_VARIANT_VERSION
#define __BUILD_NUMBER_MAJOR__ $BUILD_MAJOR_VERSION
#define __BUILD_NUMBER_MINOR__ $BUILD_MINOR_VERSION
#define __BUILD_NUMBER_VARIANT__ $BUILD_TINY_VERSION
#define __SVN_REVISION__ $SVN_REVISION
#define __FULL_BUILD_MAJOR_VERSION__ $FULL_BUILD_MAJOR_VERSION
EOF
if (defined $COPYRIGHT_END_YEAR) {
print OUTPUT_FILE "#define __COPYRIGHT_YEAR_END_TEXT__ \"$COPYRIGHT_END_YEAR\"\n";
}
close(OUTPUT_FILE);
sub packTwoValues($$)
{
my $first = shift;
my $second = shift;
die "First version component ($first) is too large. Must be between 0 and 99" if ($first > 99);
die "Second version component ($second) is too large. Must be between 0 and 999" if ($second > 999);
return $first * 1000 + $second;
}
sub splitVersion($)
{
my $PROPOSED_VERSION = shift;
$PROPOSED_VERSION =~ s/^\s+//g; # Get rid of any leading whitespace
$PROPOSED_VERSION =~ s/\s+$//g; # Get rid of any trailing whitespace
# Split out the components of the dotted version number.
my @components = split(/\./, $PROPOSED_VERSION) or die "Couldn't parse $PROPOSED_VERSION";
my $componentCount = scalar(@components);
my $BUILD_MAJOR_VERSION = $components[0];
# Have the minor and tiny components default to zero if not present.
my $BUILD_MINOR_VERSION = 0;
my $BUILD_TINY_VERSION = 0;
my $BUILD_MICRO_VERSION = 0;
my $BUILD_NANO_VERSION = 0;
if ($componentCount > 1) {
$BUILD_MINOR_VERSION = $components[1];
}
if ($componentCount > 2) {
$BUILD_TINY_VERSION = $components[2];
}
if ($componentCount > 3) {
$BUILD_MICRO_VERSION = $components[3];
}
my $RETURN_NANO_VERSION = $ENV{'RC_ProjectBuildVersion'} || $ENV{'RC_PROJECTBUILDVERSION'} || $BUILD_MICRO_VERSION;
if ($componentCount > 4) {
$BUILD_NANO_VERSION = $components[4];
$RETURN_NANO_VERSION = $BUILD_NANO_VERSION;
}
# Cut the major component down to three characters by dropping any
# extra leading digits, then adjust the major version portion of the
# version string to match.
my $originalLength = length($BUILD_MAJOR_VERSION);
my $FULL_BUILD_MAJOR_VERSION = $BUILD_MAJOR_VERSION;
$BUILD_MAJOR_VERSION =~ s/^.*(\d\d\d)$/$1/;
my $charactersToRemove = $originalLength - length($BUILD_MAJOR_VERSION);
$PROPOSED_VERSION = substr($PROPOSED_VERSION, $charactersToRemove);
return ($BUILD_MAJOR_VERSION, packTwoValues($BUILD_MINOR_VERSION, $BUILD_TINY_VERSION), packTwoValues($BUILD_MICRO_VERSION, $BUILD_NANO_VERSION), $RETURN_NANO_VERSION, $PROPOSED_VERSION, $FULL_BUILD_MAJOR_VERSION);
}