llvm-6502/utils/llvm-config/llvm-config.in.in
Reid Spencer f2722ca339 These changes are necessary to support the new llvm-config tool. llvm-config
is a handy tool for users of LLVM who want to be able to quickly get
information about LLVM's configuration. It is intended to be used in the
command line of other tools. Documentation will be forthcoming in a
subsequent patch.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26952 91177308-0d34-0410-b5e6-96231b3b80d8
2006-03-22 15:59:55 +00:00

365 lines
12 KiB
Perl

#!/usr/bin/perl
#
# Program: llvm-config
#
# Synopsis: Prints out compiler options needed to build against an installed
# copy of LLVM.
#
# Syntax: lllvm-config OPTIONS... [COMPONENTS...]
#
# This file was written by Eric Kidd, and is placed into the public domain.
#
use strict;
use warnings;
#---- begin autoconf values ----
my $VERSION = q{@PACKAGE_VERSION@};
my $PREFIX = q{@LLVM_PREFIX@};
my $BINDIR = q{@LLVM_BINDIR@};
my $INCLUDEDIR = q{@LLVM_INCLUDEDIR@};
my $LIBDIR = q{@LLVM_LIBDIR@};
my $ARCH = lc(q{@ARCH@});
my @TARGETS_BUILT = map { lc($_) } qw{@TARGETS_TO_BUILD@};
#---- end autoconf values ----
#---- begin Makefile values ----
my $CXXFLAGS = q{@LLVM_CXXFLAGS@};
my $LDFLAGS = q{@LLVM_LDFLAGS@};
my $CORE_IS_ARCHIVE = q{@CORE_IS_ARCHIVE@};
#---- end Makefile values ----
sub usage;
sub fix_library_names (@);
sub expand_dependecies (@);
sub name_map_entries;
# Parse our command-line arguments.
usage if @ARGV == 0;
my @components;
my $has_opt = 0;
my $want_libs = 0;
my $want_libnames = 0;
my $want_components = 0;
foreach my $arg (@ARGV) {
if ($arg =~ /^-/) {
if ($arg eq "--version") {
$has_opt = 1; print "$VERSION\n";
} elsif ($arg eq "--prefix") {
$has_opt = 1; print "$PREFIX\n";
} elsif ($arg eq "--bindir") {
$has_opt = 1; print "$BINDIR\n";
} elsif ($arg eq "--includedir") {
$has_opt = 1; print "$INCLUDEDIR\n";
} elsif ($arg eq "--libdir") {
$has_opt = 1; print "$LIBDIR\n";
} elsif ($arg eq "--cxxflags") {
$has_opt = 1; print "-I$INCLUDEDIR $CXXFLAGS\n";
} elsif ($arg eq "--ldflags") {
$has_opt = 1; print "-L$LIBDIR $LDFLAGS\n";
} elsif ($arg eq "--libs") {
$has_opt = 1; $want_libs = 1;
} elsif ($arg eq "--libnames") {
$has_opt = 1; $want_libnames = 1;
} elsif ($arg eq "--components") {
$has_opt = 1; print join(' ', name_map_entries), "\n";
} elsif ($arg eq "--targets-built") {
$has_opt = 1; print join(' ', @TARGETS_BUILT), "\n";
} else {
usage();
}
} else {
push @components, $arg;
}
}
# If no options were specified, fail.
usage unless $has_opt;
# If no components were specified, default to 'all'.
if (@components == 0) {
push @components, 'all';
}
# Handle any arguments which require building our dependency graph.
if ($want_libs || $want_libnames) {
my @libs = expand_dependecies(@components);
if ($want_libs) {
print join(' ', fix_library_names(@libs)), "\n";
}
if ($want_libnames) {
print join(' ', @libs), "\n";
}
}
exit 0;
#==========================================================================
# Support Routines
#==========================================================================
sub usage {
print STDERR <<__EOD__;
Usage: llvm-config <OPTION>... [<COMPONENT>...]
Get various configuration information needed to compile programs which use
LLVM. Typically called from 'configure' scripts. Examples:
llvm-config --cxxflags
llvm-config --ldflags
llvm-config --libs jitplus
Options:
--version LLVM version.
--prefix Installation prefix.
--bindir Directory containing LLVM executables.
--includedir Directory containing LLVM headers.
--libdir Directory containing LLVM libraries.
--cxxflags C++ compiler flags for files that include LLVM headers.
--ldflags Linker flags.
--libs Libraries needed to link against LLVM components.
--libnames Bare library names for in-tree builds.
--components List of all possible components.
--targets-built List of all targets currently built.
Typical components:
all All LLVM libraries (default).
native A native-code backend for this platform, if any.
jitplus All libraries needed to use the LLVM JIT examples.
__EOD__
exit(1);
}
# Use -lfoo instead of libfoo.a whenever possible, and add directories to
# files which can't be found using -L.
sub fix_library_names (@) {
my @libs = @_;
my @result;
foreach my $lib (@libs) {
# Transform the bare library name appropriately.
my ($basename) = ($lib =~ /^lib([^.]*)\.a/);
if (defined $basename) {
push @result, "-l$basename";
} else {
push @result, "$LIBDIR/$lib";
}
}
return @result;
}
#==========================================================================
# Library Dependency Analysis
#==========================================================================
# Given a few human-readable library names, find all their dependencies
# and sort them into an order which the linker will like. If we packed
# our libraries into fewer archives, we could make the linker do much
# of this work for us.
#
# Libraries have two different types of names in this code: Human-friendly
# "component" names entered on the command-line, and the raw file names
# we use internally (and ultimately pass to the linker).
#
# To understand this code, you'll need a working knowledge of Perl 5,
# and possibly some quality time with 'man perlref'.
sub load_dependencies;
sub build_name_map;
sub find_native_platform;
sub expand_names (@);
sub find_all_required_sets (@);
sub find_all_required_sets_helper ($$@);
sub maybe_fix_core (@);
# Each "set" contains one or more libraries which must be included as a
# group (due to cyclic dependencies). Sets are represented as a Perl array
# reference pointing to a list of internal library names.
my @SETS;
# Various mapping tables.
my %LIB_TO_SET_MAP; # Maps internal library names to their sets.
my %SET_DEPS; # Maps sets to a list of libraries they depend on.
my %NAME_MAP; # Maps human-entered names to internal names.
# Have our dependencies been loaded yet?
my $DEPENDENCIES_LOADED = 0;
# Given a list of human-friendly component names, translate them into a
# complete set of linker arguments.
sub expand_dependecies (@) {
my @libs = @_;
load_dependencies;
my @required_sets = find_all_required_sets(expand_names(@libs));
my @sorted_sets = topologically_sort_sets(@required_sets);
# Expand the library sets into libraries, and apply any
# platform-specific hackery.
my @result;
foreach my $set (@sorted_sets) { push @result, @{$set}; }
return maybe_fix_core(@result);
}
# Load in the raw dependency data stored at the end of this file.
sub load_dependencies {
return if $DEPENDENCIES_LOADED;
$DEPENDENCIES_LOADED = 1;
while (<DATA>) {
# Parse our line.
my ($libs, $deps) = /^(^[^:]+): ?(.*)$/;
die "Malformed dependency data" unless defined $deps;
my @libs = split(' ', $libs);
my @deps = split(' ', $deps);
# Record our dependency data.
my $set = \@libs;
push @SETS, $set;
foreach my $lib (@libs) { $LIB_TO_SET_MAP{$lib} = $set; }
$SET_DEPS{$set} = \@deps;
}
build_name_map;
}
# Build a map converting human-friendly component names into internal
# library names.
sub build_name_map {
# Add entries for all the actual libraries.
foreach my $set (@SETS) {
foreach my $lib (sort @$set) {
my $short_name = $lib;
$short_name =~ s/^(lib)?LLVM([^.]*)\..*$/$2/;
$short_name =~ tr/A-Z/a-z/;
$NAME_MAP{$short_name} = [$lib];
}
}
# Add virtual entries.
$NAME_MAP{'native'} = find_native_platform;
$NAME_MAP{'jitplus'} = ['native', 'jit', 'bcreader', 'scalaropts'];
$NAME_MAP{'all'} = [name_map_entries]; # Must be last.
}
# Figure our what native platform we should use, if any.
sub find_native_platform {
my %BUILT;
foreach my $target (@TARGETS_BUILT) { $BUILT{$target} = 1; }
if (defined $NAME_MAP{$ARCH} && defined $BUILT{$ARCH}) {
return [$ARCH];
} else {
return [];
}
}
# Get all the human-friendly component names.
sub name_map_entries {
load_dependencies;
return sort keys %NAME_MAP;
}
# Map human-readable names to internal library names.
sub expand_names (@) {
my @names = @_;
my @result;
foreach my $name (@names) {
if (defined $LIB_TO_SET_MAP{$name}) {
# We've hit bottom: An actual library name.
push @result, $name;
} elsif (defined $NAME_MAP{$name}) {
# We've found a short name to expand.
push @result, expand_names(@{$NAME_MAP{$name}});
} else {
print STDERR "llvm-config: unknown component name: $name\n";
exit(1);
}
}
return @result;
}
# Given a list of internal library names, return all sets of libraries which
# will need to be included by the linker (in no particular order).
sub find_all_required_sets (@) {
my @libs = @_;
my %sets_added;
my @result;
find_all_required_sets_helper(\%sets_added, \@result, @libs);
return @result;
}
# Recursive closures are pretty broken in Perl, so we're going to separate
# this function from find_all_required_sets and pass in the state we need
# manually, as references. Yes, this is fairly unpleasant.
sub find_all_required_sets_helper ($$@) {
my ($sets_added, $result, @libs) = @_;
foreach my $lib (@libs) {
my $set = $LIB_TO_SET_MAP{$lib};
next if defined $$sets_added{$set};
$$sets_added{$set} = 1;
push @$result, $set;
find_all_required_sets_helper($sets_added, $result, @{$SET_DEPS{$set}});
}
}
# Print a list of sets, with a label. Used for debugging.
sub print_sets ($@) {
my ($label, @sets) = @_;
my @output;
foreach my $set (@sets) { push @output, join(',', @$set); }
print "$label: ", join(';', @output), "\n";
}
# Returns true if $lib is a key in $added.
sub has_lib_been_added ($$) {
my ($added, $lib) = @_;
return defined $$added{$LIB_TO_SET_MAP{$lib}};
}
# Returns true if all the dependencies of $set appear in $added.
sub have_all_deps_been_added ($$) {
my ($added, $set) = @_;
#print_sets(" Checking", $set);
#print_sets(" Wants", $SET_DEPS{$set});
foreach my $lib (@{$SET_DEPS{$set}}) {
return 0 unless has_lib_been_added($added, $lib);
}
return 1;
}
# Given a list of sets, topologically sort them using dependencies.
sub topologically_sort_sets (@) {
my @sets = @_;
my %added;
my @result;
SCAN: while (@sets) { # We'll delete items from @sets as we go.
#print_sets("So far", reverse(@result));
#print_sets("Remaining", @sets);
for (my $i = 0; $i < @sets; ++$i) {
my $set = $sets[$i];
if (have_all_deps_been_added(\%added, $set)) {
push @result, $set;
$added{$set} = 1;
#print "Removing $i.\n";
splice(@sets, $i, 1);
next SCAN; # Restart our scan.
}
}
die "Can't find a library with no dependencies";
}
return reverse(@result);
}
# Nasty hack to work around the fact that LLVMCore changes file type on
# certain platforms.
sub maybe_fix_core (@) {
my @libs = @_;
my @result;
foreach my $lib (@libs) {
if ($lib eq "LLVMCore.o" && $CORE_IS_ARCHIVE) {
push @result, "libLLVMCore.a";
} else {
push @result, $lib;
}
}
return @result;
}
# Our library dependency data will be added after the '__END__' token, and will
# be read through the magic <DATA> filehandle.
__END__