# UCW Library configuration system: OS and C compiler
-# (c) 2005--2008 Martin Mares <mj@ucw.cz>
+# (c) 2005--2012 Martin Mares <mj@ucw.cz>
# (c) 2006 Robert Spalek <robert@ucw.cz>
# (c) 2008 Michal Vaner <vorner@ucw.cz>
return "i386";
} elsif ($mach =~ /^(x86[_-]|amd)64$/) {
return "amd64";
+ } elsif ($mach eq 'powerpc') {
+ return $mach;
} else {
return "unknown ($mach)";
}
});
-sub parse_cpuinfo_linux() {
- open X, "/proc/cpuinfo" || undef;
- my %pc = ();
- while (<X>) {
- chomp;
- /^$/ && last;
- /^([^\t]+)\t+:\s*(.*)$/ and $pc{$1}=$2;
- }
- close X;
- return ($pc{'vendor_id'},
- $pc{'cpu family'},
- $pc{'model'});
-}
-
-sub parse_cpuinfo_darwin() {
- my @cpu = (`sysctl -n machdep.cpu.vendor`,
- `sysctl -n machdep.cpu.family`,
- `sysctl -n machdep.cpu.model`);
- chomp @cpu;
- return @cpu;
-}
-
-sub parse_cpuinfo() {
- my @cpu;
- if (IsSet("CONFIG_LINUX")) {
- @cpu = parse_cpuinfo_linux();
- } elsif (IsSet("CONFIG_DARWIN")) {
- @cpu = parse_cpuinfo_darwin();
- }
- $cpu[0] = "" if !defined $cpu[0];
- $cpu[1] = 0 if !defined $cpu[1];
- $cpu[2] = 0 if !defined $cpu[2];
- return @cpu;
-}
-
-Test("CPU_ARCH", "Checking for CPU architecture", sub {
- my $mach = Get("ARCH");
- my $arch = "";
- if ($mach eq "i386") {
- Set("CPU_I386");
- UnSet("CPU_64BIT_POINTERS");
- Set("CPU_LITTLE_ENDIAN");
- UnSet("CPU_BIG_ENDIAN");
- Set("CPU_ALLOW_UNALIGNED");
- Set("CPU_STRUCT_ALIGN" => 4);
- if (IsSet("CONFIG_EXACT_CPU")) {
- my ($vendor, $family, $model) = parse_cpuinfo();
- # Try to understand CPU vendor, family and model [inspired by MPlayer's configure script]
- if ($vendor eq "AuthenticAMD") {
- if ($family >= 6) {
- if ($model >= 31 && $gccver >= 3004) { $arch = "athlon64"; }
- elsif ($model >= 6 && $gccver >= 3003) { $arch = "athlon-xp"; }
- else { $arch = "athlon"; }
- }
- } elsif ($vendor eq "GenuineIntel") {
- if ($family >= 15 && $gccver >= 3003) {
- if ($model >= 4) { $arch = "nocona"; }
- elsif ($model >= 3) { $arch = "prescott"; }
- else { $arch = "pentium4"; }
- } elsif ($family == 6 && $gccver >= 3003) {
- if ($model == 15) { $arch = "prescott"; }
- elsif (($model == 9 || $model == 13) && $gccver >= 3004) { $arch = "pentium-m"; }
- elsif ($model >= 7) { $arch = "pentium3"; }
- elsif ($model >= 3) { $arch = "pentium2"; }
- }
- }
-
- # No match on vendor, try the family
- if ($arch eq "") {
- if ($family >= 6) {
- $arch = "i686";
- } elsif ($family >= 3) {
- $arch = "i${family}86";
- }
- }
- Log (($arch ne "") ? "(using /proc/cpuinfo) " : "(don't understand /proc/cpuinfo) ");
- return $arch;
- } else {
- return "default";
- }
- } elsif ($mach eq "amd64") {
- Set("CPU_AMD64");
- Set("CPU_64BIT_POINTERS");
- Set("CPU_LITTLE_ENDIAN");
- UnSet("CPU_BIG_ENDIAN");
- Set("CPU_ALLOW_UNALIGNED");
- Set("CPU_STRUCT_ALIGN" => 8);
- if (IsSet("CONFIG_EXACT_CPU")) {
- # In x86-64 world, the detection is somewhat easier so far...
- my ($vendor, $family, $model) = parse_cpuinfo();
- if ($vendor eq "AuthenticAMD") {
- $arch = "athlon64";
- } elsif ($vendor eq "GenuineIntel") {
- $arch = "nocona";
- }
- Log (($arch ne "") ? "(using /proc/cpuinfo) " : "(don't understand /proc/cpuinfo) ");
- return $arch;
- } else {
- return "default";
- }
- } else {
- return "unknown";
- }
-});
-
-if (Get("CPU_ARCH") eq "unknown") {
- Warn "CPU architecture not recognized, using defaults, keep fingers crossed.\n";
+my $arch = Get("ARCH");
+if ($arch eq 'i386') {
+ Set("CPU_I386");
+ UnSet("CPU_64BIT_POINTERS");
+ Set("CPU_LITTLE_ENDIAN");
+ UnSet("CPU_BIG_ENDIAN");
+ Set("CPU_ALLOW_UNALIGNED");
+ Set("CPU_STRUCT_ALIGN" => 4);
+} elsif ($arch eq "amd64") {
+ Set("CPU_AMD64");
+ Set("CPU_64BIT_POINTERS");
+ Set("CPU_LITTLE_ENDIAN");
+ UnSet("CPU_BIG_ENDIAN");
+ Set("CPU_ALLOW_UNALIGNED");
+ Set("CPU_STRUCT_ALIGN" => 8);
+} elsif ($arch eq "powerpc") {
+ Set("CPU_AMD64");
+ UnSet("CPU_64BIT_POINTERS");
+ UnSet("CPU_LITTLE_ENDIAN");
+ Set("CPU_BIG_ENDIAN");
+ UnSet("CPU_ALLOW_UNALIGNED");
+ Set("CPU_STRUCT_ALIGN" => 4);
+} elsif (!Get("CPU_LITTLE_ENDIAN") && !Get("CPU_BIG_ENDIAN")) {
+ Fail "Architecture not recognized, please set CPU_xxx variables manually.";
}
### Compiler and its Options ###
# C optimizations
Set("COPT" => '-O2');
-if (Get("CPU_ARCH") ne "unknown" && Get("CPU_ARCH") ne "default") {
- Append("COPT", '-march=$(CPU_ARCH)');
+if ($arch =~ /^(i386|amd64)$/ && Get("CONFIG_EXACT_CPU")) {
+ if ($gccver >= 4002) {
+ Append('COPT', '-march=native');
+ } else {
+ Warn "CONFIG_EXACT_CPU not supported with old GCC, ignoring.\n";
+ }
}
# C optimizations for highly exposed code
Set("COPT2" => '-O3');
# Warnings
-Set("CWARNS" => '-Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Winline');
+Set("CWARNS" => '-Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes');
Set("CWARNS_OFF" => '');
# Linker flags
# Extra flags for compiling and linking shared libraries
Set("CSHARED" => '-fPIC');
-if (IsSet("CONFIG_LOCAL")) {
- Set("SONAME_PREFIX" => "lib/");
-} else {
- Set("SONAME_PREFIX" => "");
+Append("LOPT" => "-Wl,--rpath-link,run/lib -Lrun/lib");
+if (!IsSet("CONFIG_LOCAL")) {
+ # Beware that in non-local builds the INSTALL_LIB_DIR must exist in
+ # standard search paths for shared libraries.
+ Set("SO_LINK_PATH" => '');
+}
+else {
+ # In local builds, we need to link binaries with custom --rpath.
+ # GCC seems to fail when this directory does not exist.
+ Set("SO_LINK_PATH" => "-Wl,--rpath," . Get("INSTALL_LIB_DIR"));
+ AtWrite {
+ my $libdir = Get("INSTALL_LIB_DIR");
+ if (IsSet("CONFIG_SHARED")) {
+ `mkdir -p $libdir`; Fail("Cannot create $libdir") if $?;
+ }
+ };
}
if (IsSet("CONFIG_DARWIN")) {
- Set("LSHARED" => '-dynamiclib -install_name $(SONAME_PREFIX)$(@F)$(SONAME_SUFFIX) -undefined dynamic_lookup');
+ Set("LSHARED" => '-dynamiclib -install_name $(@F)$(SONAME_SUFFIX) -undefined dynamic_lookup');
} else {
- Set("LSHARED" => '-shared -Wl,-soname,$(SONAME_PREFIX)$(@F)$(SONAME_SUFFIX)');
+ Set("LSHARED" => '-shared -Wl,-soname,$(@F)$(SONAME_SUFFIX)');
}
# Extra switches depending on GCC version:
Append("CWARNS" => "-Wundef -Wredundant-decls -Wno-pointer-sign -Wdisabled-optimization -Wno-missing-field-initializers");
Append("CWARNS_OFF" => "-Wno-pointer-sign");
Append("COPT" => "-finline-limit=5000 --param large-function-insns=5000 --param inline-unit-growth=200 --param large-function-growth=400");
- if ($gccver >= 4002) {
- Append("COPT" => "-fgnu89-inline");
- }
} else {
Warn "Don't know anything about this GCC version, using default switches.\n";
}
Append("LOPT" => "-s");
}
+# Link-time optimization (experimental)
+# This is currently very inefficient, because we do not attempt to disable
+# optimizations when compiling individual modules. Therefore, we optimize
+# each shared library module twice: when compiling and when linking.
+# Doing it properly would require hacking makefiles.
+if (IsSet("CONFIG_LTO")) {
+ Append("LOPT", "-flto");
+ Append("COPT", "-flto");
+}
+
if (IsSet("CONFIG_DARWIN")) {
# gcc-4.0 on Darwin doesn't set this in the gnu99 mode
Append("CLANG" => "-fnested-functions");
# Directory hierarchy of the fink project
Append("LIBS" => "-L/sw/lib");
Append("COPT" => "-I/sw/include");
- # Fill in some constants not found in the system header files
- Set("SOL_TCP" => 6); # missing in /usr/include/netinet/tcp.h
+}
+
+### Compiling test programs ###
+
+sub TestCompile($$) {
+ my ($testname, $source) = @_;
+ my $dir = "conftest-$testname";
+ `rm -rf $dir && mkdir $dir`; $? and Fail "Cannot initialize $dir";
+
+ open SRC, ">$dir/conftest.c";
+ print SRC $source;
+ close SRC;
+
+ my $cmd = join(" ",
+ map { defined($_) ? $_ : "" }
+ "cd $dir &&",
+ Get("CC"), Get("CLANG"), Get("COPT"), Get("CEXTRA"), Get("LIBS"),
+ "conftest.c", "-o", "conftest",
+ ">conftest.log", "2>&1"
+ );
+ `$cmd`;
+ my $result = !$?;
+
+ `rm -rf $dir` unless Get("KEEP_CONFTEST");
+
+ return $result;
}
### Writing C headers with configuration ###