debian/0000775000000000000000000000000012253225223007166 5ustar debian/rules0000775000000000000000000000632112146202552010251 0ustar #!/usr/bin/make -f export DH_VERBOSE=1 LDFLAGS+=-Wl,--as-needed TOPDIR=$(shell pwd) NS3_DIR=$(shell ls -d ns-*) PYBINDGENV_DIR=$(shell ls -d pybindgen-*) REFTRACE_DIR=$(shell ls -d ns-*-ref-traces) NSC_DIR=$(shell ls -d nsc-*) RELEASE=debug ###check system memory, if it is less than 3GiB, use "-j1" when build MEMORY=$(shell awk '/MemTotal:/{print $$2}' /proc/meminfo) BUILD_OPTION=$(shell if [ $(MEMORY) -lt 3090252 ]; then echo "-j1"; fi) CPU_CORES=$(shell nproc) BUILD_OPTION_OPTIPNG=$(shell echo "-j$(CPU_CORES)") %: dh $@ --with python2 build-indep: build-doc-stamp build-doxygen-stamp optimize-doc-size-stamp optimize-doc-size-stamp: build-doc-stamp build-doxygen-stamp sh debian/duplicate-files.sh ns-3.*/doc/html make $(BUILD_OPTION_OPTIPNG) -f debian/optipng.mk touch $@ build-doc-stamp: make html man -C ./$(NS3_DIR)/doc/manual/ make html man -C ./$(NS3_DIR)/doc/models/ make html man -C ./$(NS3_DIR)/doc/tutorial/ rm ns-3.*/doc/*/build/*/_static/jquery.js rm ns-3.*/doc/*/build/*/_static/underscore.js touch $@ build-doxygen-stamp: build-shared cd $(NS3_DIR); ./waf --doxygen touch $@ override_dh_auto_configure: #cp ./debian/upstream-back/build.config ./.config ############################################## # build and copy waf cd debian/waf-1.7; ./configure; cp waf $(TOPDIR)/$(NS3_DIR); make distclean cd debian/waf-1.6; ./configure; cp waf $(TOPDIR)/$(PYBINDGENV_DIR); make distclean override_dh_auto_build: build-static build-shared sed -i 's/-Wl,-Bdynamic//g' debian/tmp/usr/lib/pkgconfig/*.pc build-static: ###### build and install static libraries ./build.py --disable-netanim --build-options="$(BUILD_OPTION)" -- --prefix=/usr --enable-static --enable-mpi -d release -o build-static cd ./$(NS3_DIR);./waf install --destdir=../debian/tmp build-shared: build-static ####### build and install shared libraries, python bindings for default python. ./build.py --disable-netanim --enable-tests --build-options="$(BUILD_OPTION)" -- --prefix=/usr --enable-mpi -d release -o build-shared cd ./$(NS3_DIR);./waf install --destdir=../debian/tmp override_dh_auto_test: -cd ./$(NS3_DIR); ./test.py -v override_dh_prep: #I install files here when build. #The upstream cannot work well for us. #I will remove this dir when dh_clean, surely. dh_prep -Xdebian/tmp override_dh_auto_install: # they are installed in auto_build override_dh_python2: #### upstream now can only build for the default version of python. dh_python2 --no-guessing-versions override_dh_installchangelogs: dh_installchangelogs ./$(NS3_DIR)/CHANGES.html override_dh_strip: dh_strip -plibns3-3 --dbg-package=libns3-3-dbg dh_strip -ppython-ns3 --dbg-package=python-ns3-dbg dh_strip override_dh_auto_clean: -sh ./debian/clean-tree.sh dh_auto_clean override_dh_compress: dh_compress -Xusr/share/doc/ns3/doxygen/ -Xusr/share/doc/ns3/manual/ -Xusr/share/doc/ns3/models/ -Xusr/share/doc/ns3/tutorial/ override_dh_builddeb: dh_builddeb -- -Zxz dfsg: for i in `find -name waf`;do \ if [ "$$(stat --format='%s' $$i)" -gt 10000 ];then rm -f $$i; fi;\ done UP_V=$$(ls -d ns-3.*| cut -d '-' -f2); \ DIR_NAME=$$(pwd |xargs basename);\ cd ..;\ tar --exclude-vcs --exclude=debian --exclude=.pc -cJf ns3_$${UP_V}+dfsg.orig.tar.xz $${DIR_NAME} debian/optipng.mk0000664000000000000000000000027712114302721011200 0ustar FILES := $(shell find ns-3.*/doc/html/ -type f -name '*_*_*.png' -printf "%p\t") TARGETS := $(FILES:=-update) all: $(TARGETS) %-update: % optipng -preserve -quiet -fix -o 5 $< .PHONY: all debian/watch0000664000000000000000000000016412114116777010231 0ustar version=3 opts="dversionmangle=s/(3.\d\d)\+dfsg1/$1/" \ http://www.nsnam.org/release/ns-allinone-([\d.]+)\.tar\.bz2 debian/changelog0000664000000000000000000001214212253225206011041 0ustar ns3 (3.17+dfsg-1build1) trusty; urgency=medium * No-change rebuild for libopenmpi1.3 -> libopenmpi1.6 transition. -- Logan Rosen Sat, 14 Dec 2013 23:05:20 -0500 ns3 (3.17+dfsg-1) unstable; urgency=low * New upstream release 3.17. * Bump waf to 1.7 and 1.6. -- YunQiang Su Sun, 19 May 2013 01:00:55 +0800 ns3 (3.16+dfsg1-1) unstable; urgency=low * remove duplicate files and do optipng in ns3-doc. * d/watch to watch http://www.nsnam.org/release/ * Imported Upstream version 3.16 * Bump standard version to 3.9.4 * Build-depen on libgraphviz-dev to enable visualizer python-pygoocanvas, python-pygraphviz to build-dep instead of build-dep-indep -- YunQiang Su Fri, 01 Mar 2013 20:39:22 +0800 ns3 (3.15+dfsg-1) unstable; urgency=low * New upstream release. -- YunQiang Su Sun, 09 Sep 2012 20:15:00 +0800 ns3 (3.14.1+dfsg-1) unstable; urgency=low * New upstream release. -- YunQiang Su Wed, 13 Jun 2012 16:13:28 +0800 ns3 (3.13+dfsg-1) unstable; urgency=low [ Aron Xu ]: add tag binary and binary-indep, for not build doc when --binary-arch (Closes: #654493). [ YunQiang Su ] add waf 1.5/1.6 source to debian directory, and build waf from there (Closes: #642217). [ Upstream ] Successfully link with --as-needed option (Closes: #642225). -- YunQiang Su Fri, 06 Jan 2012 00:35:42 +0800 ns3 (3.13-1) unstable; urgency=low * New upstream release. * Linked with --as-needed option. -- YunQiang Su Sat, 24 Dec 2011 18:15:24 +0800 ns3 (3.12.1+dfsg1-5) unstable; urgency=low * doesn't depend on procps, read /proc/meminfo directly. * build for python2.7 as defaut python. * build depend on only default python instead of python-all. * bump compat to 9 to use dpkg-buildflags to export CFLAGS etc by default like before. -- YunQiang Su Sun, 02 Oct 2011 04:52:16 +0000 ns3 (3.12.1+dfsg1-4) unstable; urgency=low [debian/rules]: fix the call of awk: $ -> $$ [debian/control]: add build depends of procps to get the memory. -- YunQiang Su Thu, 22 Sep 2011 14:13:34 +0800 ns3 (3.12.1+dfsg1-3) unstable; urgency=low [debian/rules]: * add -v option to test.py to show more details. * use '-j1' option to build when memory is less than 3GiB. * disable "--as-needed" temporarily, the upstream claimed that it will be fixed in next release. [build.py]: * drop "--doxygen-no-build", which is not for configure. * new build.py with --build-option and "-- --options-for-waf" . -- Thanks to Gustavo J. A. M. Carneiro . -- YunQiang Su Wed, 21 Sep 2011 01:45:49 +0800 ns3 (3.12.1+dfsg1-2) unstable; urgency=low * fix the issue that doesn't generate on non-x86 and non-linux arch [ns3-static.diff]. -- YunQiang Su Mon, 19 Sep 2011 18:23:02 +0800 ns3 (3.12.1+dfsg1-1) unstable; urgency=low New Upstream version. [ Aron Xu ] * Correct Vcs-Browser field. [ YunQiang Su ] * Imported Upstream version 3.12 * drop , models-doc-ftbfs.diff, modules-so-version.diff; fixed in upstream * remove build-py-ns3-option.diff and gen-static-libraries.diff, use another way to do it: upstream-back/*. * add some build-dep-indep the last version lost.(Closes: #634544) * Only install python modules for default version(Closes: #628909): How to build it for multi versions of python? * run test after build (Closes: #630184). * transit to dh_python2 (Closes: #637518). * New debug packages: libns3-3-dbg and python-ns3-dbg. -- YunQiang Su Thu, 1 Sep 2011 13:14:23 +0800 ns3 (3.11+dfsg1-1) unstable; urgency=low * New Upstream Version * rm waf bin file (dfsg) and add waf source files * doxygen itself depends on doxygen-latex now (Closes: #616271) * Close an invaild FTBFS (Closes: #625011) * Remove waf bin file from orig tar * More details in debian/copyright -- YunQiang Su Fri, 27 May 2011 14:26:47 +0800 ns3 (3.9-1) unstable; urgency=low * fix dep of libns3-dev,add libns3-3 * add Build-Conflicts: libmpich2-dev * modify descripts (Closes: #579311) * fix virtual-network-setup.sh bashism (Closes: #581476) * port to Debian Policy 3.9.0 -- YunQiang Su Sat, 21 Aug 2010 14:15:10 +0800 ns3 (3.8-3) unstable; urgency=low * Open debug and fix Bug#582926 :Possible uses -march=native * fix python-ns3 * add build dep libxml2-dev libgsl0-dev -- YunQiang Su May, 21 Sun 2010 20:09:10 +0800 ns3 (3.8-2) unstable; urgency=low * Some arch have no libopenmpi-dev,so remove it on these arch * add override_auto_clean -- YunQiang Su May, 19 Sun 2010 15:09:10 +0800 ns3 (3.8-1) unstable; urgency=low * New Upstream version -- YunQiang Su May, 9 Sun 2010 12:22:35 +0800 ns3 (3.7.1-7) unstable; urgency=low * Initial release (Closes: #574471) -- YunQiang Su Thu, 18 Mar 2010 21:28:35 +0800 debian/waf-1.7/0000775000000000000000000000000012253225221010244 5ustar debian/waf-1.7/utils/0000775000000000000000000000000012145745420011414 5ustar debian/waf-1.7/utils/launcher/0000775000000000000000000000000012145745420013215 5ustar debian/waf-1.7/utils/launcher/wscript0000664000000000000000000000025112145745420014631 0ustar out = 'waf-launcher/bin/Release' def configure(config): config.load('cs') def build(bld): bld(features='cs',source='waf-launcher/Main.cs', type='exe',gen='waf.exe') debian/waf-1.7/utils/launcher/README.md0000664000000000000000000000252412145745420014477 0ustar #Waf-launcher This is a simple wrapper for the [waf build system](http://code.google.com/p/waf/) Since many windows users does not have python installed by default, the exe file from this project can be included along with the copy of waf to wrap waf to install python on demand. The requirements is only .Net 2.0 whics is either Windows Server 2003 R2 and up, or Windows Vista and up. There is a good chance it is installed in many OEM installs of Windows XP as well ##How to compile use either waf or monodevelop (wscript and project files is in the repository) ##How to use Assume we have a repository, myrepo, where wscript and waf already exists. myrepo/waf myrepo/wscript now copy waf-launcher/bin/Release/waf.exe to the repository myrepo/waf.exe Linux users can continue to use `./waf`, just like Windows users can continue to use `python waf` For Windows users there is now a second way to invoke waf by writing either `waf.exe` or simply just `waf`. When the Windows users does that the following happens: 1. It tries "python waf" 2. If 1 failed it tries "C:\python27\python.exe waf" 3. If 2 failed it ask for permission to install python 4. If pemission is given it tries to install python silently 5. step 1 and 2 it done again 6. If this still fails we exit with an error Any arguments to `waf.exe` is passed on to `waf` debian/waf-1.7/utils/launcher/waf-launcher.sln0000664000000000000000000000163012145745420016307 0ustar  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "waf-launcher", "waf-launcher\waf-launcher.csproj", "{63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Debug|x86.ActiveCfg = Debug|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Debug|x86.Build.0 = Debug|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Release|x86.ActiveCfg = Release|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = waf-launcher\waf-launcher.csproj version = 1.0 EndGlobalSection EndGlobal debian/waf-1.7/utils/launcher/LICENSE0000664000000000000000000000247212145745420014227 0ustar 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. debian/waf-1.7/utils/launcher/waf-launcher/0000775000000000000000000000000012145745420015571 5ustar debian/waf-1.7/utils/launcher/waf-launcher/Main.cs0000664000000000000000000000646712145745420017021 0ustar using System; using System.Diagnostics; namespace waflauncher { class MainClass { public static System.Diagnostics.Process exec(string command,params string[] args) { String argstring = String.Join(" ",args); System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo(command,argstring); startinfo.UseShellExecute = false; System.Diagnostics.Process p; try { p = Process.Start(startinfo); } catch (System.ComponentModel.Win32Exception){ return null; } p.WaitForExit(); return p; } public static int Main (string[] args) { //I run waf and if not succesful we try on-the-fly install of python if(!runWaf(args)){ //but first we ask the user if it's okay to install software on their computer if(mayInstall()){ //I install python and try running waf yet another time installPython(); if(!runWaf(args)){ //If it still fails something has gone horrible wrong Console.WriteLine("Python not fully working"); return 1; } } else { Console.WriteLine("Not automatically installing Python"); Console.WriteLine("Please download and install http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi"); Console.WriteLine("or if you have python installed make sure it is on %PATH%"); Console.WriteLine("or run this command again and answer yes"); } } return 0; } public static bool mayInstall() { Console.Write("Download and install python [Y/n]? "); ConsoleKeyInfo a = Console.ReadKey(); Console.WriteLine(); switch(a.KeyChar){ case 'Y': case 'y': case '\n': case '\r': return true; //If unsure default to not doing it default: return false; } } public static String getwafDir(){ //This changes the current directory to the place where the exe exists System.Reflection.Assembly a = System.Reflection.Assembly.GetEntryAssembly(); String path = System.IO.Path.GetDirectoryName(a.Location); return path + System.IO.Path.DirectorySeparatorChar; } public static bool runWaf(string[] args){ Process p = exec("python", getwafDir() + "waf", String.Join(" ",args)); //If command could be execeuted return true if (p != null) return true; //If not try with the direct path to the default installation which is where installPython() will install it to //This is done since the %PATH% variable might not be setup to include python List versions = new List() { "27", "32", "26", "31", "25", "30" }; foreach (String v in versions) { p = exec("C:\\Python"+v+"\\python.exe", "waf", String.Join(" ",args)); if (p != null) return true; } return false; } public static void installPython(){ //Make a filename to download python to String filename = System.IO.Path.GetTempPath() + Char.ToString(System.IO.Path.DirectorySeparatorChar) + "python-2.7.1.msi"; System.Net.WebClient web = new System.Net.WebClient(); Console.WriteLine ("Downloading python 2.7"); web.DownloadFile("http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi",filename); Console.WriteLine ("python2.7 downloaded to " + filename); Console.WriteLine ("Installing python"); //filename must be qouted or else msiexec will fail exec("msiexec","/qn","/i","\"" +filename + "\""); Console.WriteLine ("Python is now installed"); } } } debian/waf-1.7/utils/launcher/waf-launcher/AssemblyInfo.cs0000664000000000000000000000172212145745420020515 0ustar using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("waf-launcher")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] debian/waf-1.7/utils/launcher/waf-launcher/waf-launcher.csproj0000664000000000000000000000361412145745420021373 0ustar Debug x86 9.0.21022 2.0 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3} Exe waflauncher waf v3.5 1.0 true full false bin\Debug DEBUG prompt 4 x86 true none false bin\Release prompt 4 x86 true debian/waf-1.7/utils/genbench.py0000775000000000000000000002253612145745420013552 0ustar #!/usr/bin/python # encoding: utf-8 import sys import os.path from random import Random random = Random(0) # initialise with seed to have reproductible benches # for example: ./genbench.py /tmp/build 50 100 15 5 HELP_USAGE = """Usage: generate_libs.py root libs classes internal external. root - Root directory where to create libs. libs - Number of libraries (libraries only depend on those with smaller numbers) classes - Number of classes per library internal - Number of includes per file referring to that same library external - Number of includes per file pointing to other libraries To try the waf part, do: waf configure build -p -j5 To test the autotools part, do: touch README AUTHORS NEWS ChangeLog && autoreconf --install --symlink --verbose && mkdir autotools-build-dir && cd autotools-build-dir && ../configure --disable-shared CXXFLAGS=-Wall && time make -j4 --silent && time make -j4 --silent """ def lib_name(i): return "lib_" + str(i) def createHeader(name): filename = name + ".h" handle = open(filename, "w" ) guard = name + '_h_' handle.write ('#ifndef ' + guard + '\n'); handle.write ('#define ' + guard + '\n\n'); handle.write ('class ' + name + ' {\n'); handle.write ('public:\n'); handle.write (' ' + name + '();\n'); handle.write (' ~' + name + '();\n'); handle.write ('};\n\n'); handle.write ('#endif\n'); def createCPP(name, lib_number, classes_per_lib, internal_includes, external_includes): filename = name + ".cpp" handle = open(filename, "w" ) header= name + ".h" handle.write ('#include "' + header + '"\n'); includes = random.sample(range(classes_per_lib), internal_includes) for i in includes: handle.write ('#include "class_' + str(i) + '.h"\n') if (lib_number > 0): includes = random.sample(range(classes_per_lib), external_includes) lib_list = range(lib_number) for i in includes: libname = 'lib_' + str(random.choice(lib_list)) handle.write ('#include <' + libname + '/' + 'class_' + str(i) + '.h>\n') handle.write ('\n'); handle.write (name + '::' + name + '() {}\n'); handle.write (name + '::~' + name + '() {}\n'); def createSConscript(lib_number, classes): handle = open("SConscript", "w"); handle.write("Import('env')\n") handle.write('list = Split("""\n'); for i in range(classes): handle.write(' class_' + str(i) + '.cpp\n') handle.write(' """)\n\n') handle.write('env.StaticLibrary("lib_' + str(lib_number) + '", list)\n\n') def createLibCMakeLists(lib_number, classes): handle = open("CMakeLists.txt", "w") handle.write("""add_library(lib_%s STATIC %s)\n""" % (str(lib_number), ' '.join(('class_%s' % str(i) for i in range(classes))))) def createLibMakefile(lib_number, classes): handle = open("Makefile", "w"); handle.write ("""COMPILER = g++ INC = -I.. CCFLAGS = -g -Wall $(INC) ARCHIVE = ar DEPEND = makedepend .SUFFIXES: .o .cpp """) handle.write ("lib = lib_" + str(lib_number) + ".a\n") handle.write ("src = \\\n") for i in range(classes): handle.write('class_' + str(i) + '.cpp \\\n') handle.write (""" objects = $(patsubst %.cpp, %.o, $(src)) all: depend $(lib) $(lib): $(objects) $(ARCHIVE) cr $@ $^ touch $@ .cpp.o: $(COMPILER) $(CCFLAGS) -c $< clean: @rm $(objects) $(lib) 2> /dev/null depend: @$(DEPEND) $(INC) $(src) """) def createLibJamFile(lib_number, classes): handle = open("Jamfile", "w") handle.write ("SubDir TOP lib_" + str(lib_number) + " ;\n\n") handle.write ("SubDirHdrs $(INCLUDES) ;\n\n") handle.write ("Library lib_" + str(lib_number) + " :\n") for i in range(classes): handle.write(' class_' + str(i) + '.cpp\n') handle.write (' ;\n') def createVCProjFile(lib_number, classes): handle = open("lib_" + str(lib_number) + ".vcproj", "w") handle.write(""" """) for i in range(classes): handle.write(' \n') handle.write(""" """) def createLibrary(lib_number, classes, internal_includes, external_includes): name = "lib_" + str(lib_number) setDir(name) for i in range(classes): classname = "class_" + str(i) createHeader(classname) createCPP(classname, lib_number, classes, internal_includes, external_includes) createSConscript(lib_number, classes) createLibCMakeLists(lib_number, classes) createLibMakefile(lib_number, classes) createAutotools(lib_number, classes) os.chdir("..") def createCMakeLists(libs): handle = open("CMakeLists.txt", "w") handle.write("""project('profiling-test') cmake_minimum_required(VERSION 2.8) include_directories(${CMAKE_SOURCE_DIR}) """) for i in range(libs): handle.write("""add_subdirectory(lib_%s)\n""" % str(i)) def createSConstruct(libs): handle = open("SConstruct", "w"); handle.write("""env = Environment(CPPFLAGS=['-Wall'], CPPDEFINES=['LINUX'], CPPPATH=[Dir('#')])\n""") handle.write("""env.Decider('timestamp-newer')\n""") handle.write("""env.SetOption('implicit_cache', True)\n""") handle.write("""env.SourceCode('.', None)\n""") for i in range(libs): handle.write("""env.SConscript("lib_%s/SConscript", exports=['env'])\n""" % str(i)) def createFullMakefile(libs): handle = open("Makefile", "w") handle.write('subdirs = \\\n') for i in range(libs): handle.write('lib_' + str(i) + '\\\n') handle.write(""" all: $(subdirs) @for i in $(subdirs); do \ $(MAKE) -C $$i all; done clean: @for i in $(subdirs); do \ (cd $$i; $(MAKE) clean); done depend: @for i in $(subdirs); do \ (cd $$i; $(MAKE) depend); done """) def createFullJamfile(libs): handle = open("Jamfile", "w") handle.write ("SubDir TOP ;\n\n") for i in range(libs): handle.write('SubInclude TOP ' + lib_name(i) + ' ;\n') handle = open("Jamrules", "w") handle.write('INCLUDES = $(TOP) ;\n') WT = """#! /usr/bin/env python # encoding: utf-8 VERSION = '0.0.2' APPNAME = 'build_bench' top = '.' out = 'out' def configure(conf): conf.load('g++') def build(bld): for i in range(%d): filez = ' '.join(['lib_%%d/class_%%d.cpp' %% (i, j) for j in range(%d)]) bld.stlib( source = filez, target = 'lib_%%d' %% i, includes = '.', # include the top-level ) """ def createWtop(libs, classes): f = open('wscript', 'w') f.write(WT % (libs, classes)) f.close() def createFullSolution(libs): handle = open("solution.sln", "w") handle.write("Microsoft Visual Studio Solution File, Format Version 8.00\n") for i in range(libs): project_name = lib_name(i) + '\\' + lib_name(i) + '.vcproj' handle.write('Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "' + lib_name(i) + '", "' + project_name + '", "{CF495178-8865-4D20-939D-AAA' + str(i) + '}"\n') handle.write('EndProject\n') def createAutotoolsTop(libs): handle = open("configure.ac", "w") handle.write('''\ AC_INIT([bench], [1.0.0]) AC_CONFIG_AUX_DIR([autotools-aux]) AM_INIT_AUTOMAKE([subdir-objects nostdinc no-define tar-pax dist-bzip2]) AM_PROG_LIBTOOL AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ''') handle = open("Makefile.am", "w") handle.write('''\ AM_CPPFLAGS = -I$(srcdir) lib_LTLIBRARIES = ''') for i in range(libs): handle.write('include lib_%s/Makefile.am\n' % str(i)) def createAutotools(lib_number, classes): handle = open("Makefile.am", "w") handle.write('''\ lib_LTLIBRARIES += lib%s.la lib%s_la_SOURCES =''' % (str(lib_number), str(lib_number))) for i in range(classes): handle.write(' lib_%s/class_%s.cpp' % (str(lib_number), str(i))) handle.write('\n') def setDir(dir): if (not os.path.exists(dir)): os.mkdir(dir) os.chdir(dir) def main(argv): if len(argv) != 6: print(HELP_USAGE) return root_dir = argv[1] libs = int(argv[2]) classes = int(argv[3]) internal_includes = int(argv[4]) external_includes = int(argv[5]) setDir(root_dir) for i in range(libs): createLibrary(i, classes, internal_includes, external_includes) createSConstruct(libs) createCMakeLists(libs) createFullMakefile(libs) createWtop(libs, classes) createAutotoolsTop(libs) if __name__ == "__main__": main( sys.argv ) debian/waf-1.7/utils/waf.bat0000664000000000000000000000414112145745420012661 0ustar @echo off rem from issue #964 Setlocal EnableDelayedExpansion rem Check Windows Version set TOKEN=tokens=3* ver | findstr /i "5\.0\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "5\.1\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "5\.2\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "6\.0\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=2* ver | findstr /i "6\.1\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=2* rem Start calculating PYTHON and PYTHON_DIR set PYTHON= set PYTHON_DIR= Setlocal EnableDelayedExpansion set PYTHON_DIR_OK=FALSE set REGPATH= for %%i in (3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0 2.7 2.6 2.5 2.4 2.3) do ( for %%j in (HKCU HKLM) do ( for %%k in (SOFTWARE\Wow6432Node SOFTWARE) do ( for %%l in (Python\PythonCore IronPython) do ( set REG_PYTHON_EXE=python.exe if "%%l"=="IronPython" ( set REG_PYTHON_EXE=ipy.exe ) @echo on set REGPATH=%%j\%%k\%%l\%%i\InstallPath rem @echo Regpath !REGPATH! REG QUERY "!REGPATH!" /ve 1>nul 2>nul if !ERRORLEVEL! equ 0 ( for /F "%TOKEN% delims= " %%A IN ('REG QUERY "!REGPATH!" /ve') do @set REG_PYTHON_DIR=%%B if exist !REG_PYTHON_DIR! ( set REG_PYTHON=!REG_PYTHON_DIR!!REG_PYTHON_EXE! rem set PYTHON_DIR_OK=TRUE if "!PYTHON_DIR_OK!"=="FALSE" ( set PYTHON_DIR=!REG_PYTHON_DIR! set PYTHON=!REG_PYTHON! set PYTHON_DIR_OK=TRUE ) rem set PYTHON_DIR_OK=FALSE rem @echo Find !REG_PYTHON! rem goto finished ) ) echo off ) rem for l ) rem for k ) rem for j ) rem for i :finished Endlocal & SET PYTHON_DIR=%PYTHON_DIR% & SET PYTHON=%PYTHON% if "%PYTHON_DIR%" == "" ( rem @echo No Python dir set PYTHON=python goto running ) rem @echo %PYTHON_DIR% if "%PYTHON%" == "" ( rem @echo No Python set PYTHON=python goto running ) set PYTHON_INCLUDE=%PYTHON_DIR%include set PYTHON_LIB=%PYTHON_DIR%libs\python27.lib set PATH=%PYTHON_DIR%;%PYTHON_DIR%Scripts;%PYTHON_DIR%Tools\Scripts;%PATH% :running @echo Using %PYTHON% "%PYTHON%" -x "%~dp0waf" %* & Endlocal & exit /b debian/waf-1.7/wscript0000664000000000000000000002351712145745420011702 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 """ to make a custom waf file use the option --tools To add a tool that does not exist in the folder compat15, pass an absolute path: ./waf-light --make-waf --tools=compat15,/comp/waf/aba.py --prelude=$'\tfrom waflib.extras import aba\n\taba.foo()' """ VERSION="1.7.10" APPNAME='waf' REVISION='' top = '.' out = 'build' demos = ['cpp', 'qt4', 'tex', 'ocaml', 'kde3', 'adv', 'cc', 'idl', 'docbook', 'xmlwaf', 'gnome'] zip_types = ['bz2', 'gz'] PRELUDE = '' #from tokenize import * import tokenize import os, sys, re, io, optparse from waflib import Utils, Options, Logs from hashlib import md5 from waflib import Configure Configure.autoconfig = 1 def sub_file(fname, lst): f = open(fname, 'rU') try: txt = f.read() finally: f.close() for (key, val) in lst: re_pat = re.compile(key, re.M) txt = re_pat.sub(val, txt) f = open(fname, 'w') try: f.write(txt) finally: f.close() def to_bytes(x): if sys.hexversion>0x300000f: return x.encode() return x print("------> Executing code from the top-level wscript <-----") def init(ctx): if Options.options.setver: # maintainer only (ita) ver = Options.options.setver hexver = Utils.num2ver(ver) hexver = '0x%x'%hexver sub_file('wscript', (('^VERSION=(.*)', 'VERSION="%s"' % ver), )) sub_file('waf-light', (('^VERSION=(.*)', 'VERSION="%s"' % ver), )) pats = [] pats.append(('^WAFVERSION=(.*)', 'WAFVERSION="%s"' % ver)) pats.append(('^HEXVERSION(.*)', 'HEXVERSION=%s' % hexver)) try: rev = ctx.cmd_and_log("git rev-parse HEAD").strip() pats.append(('^WAFREVISION(.*)', 'WAFREVISION="%s"' % rev)) except Exception: pass sub_file('waflib/Context.py', pats) sys.exit(0) def check(ctx): Logs.warn('Nothing to do') # this function is called before any other for parsing the command-line def options(opt): # generate waf opt.add_option('--make-waf', action='store_true', default=False, help='creates the waf script', dest='waf') opt.add_option('--zip-type', action='store', default='bz2', help='specify the zip type [Allowed values: %s]' % ' '.join(zip_types), dest='zip') opt.add_option('--make-batch', action='store_true', default=False, help='creates a convenience waf.bat file (done automatically on win32 systems)', dest='make_batch') opt.add_option('--yes', action='store_true', default=False, help=optparse.SUPPRESS_HELP, dest='yes') # those ones are not too interesting opt.add_option('--set-version', default='', help='sets the version number for waf releases (for the maintainer)', dest='setver') opt.add_option('--strip', action='store_true', default=True, help='shrinks waf (strip docstrings, saves 33kb)', dest='strip_comments') opt.add_option('--nostrip', action='store_false', help='no shrinking', dest='strip_comments') opt.add_option('--tools', action='store', help='Comma-separated 3rd party tools to add, eg: "compat,ocaml" [Default: "compat15"]', dest='add3rdparty', default='compat15') opt.add_option('--prelude', action='store', help='Code to execute before calling waf', dest='prelude', default=PRELUDE) opt.load('python') def compute_revision(): global REVISION def visit(arg, dirname, names): for pos, name in enumerate(names): if name[0] == '.' or name in ['_build_', 'build']: del names[pos] elif name.endswith('.py'): arg.append(os.path.join(dirname, name)) sources = [] os.path.walk('waflib', visit, sources) sources.sort() m = md5() for source in sources: f = open(source,'rb') readBytes = 100000 while (readBytes): readString = f.read(readBytes) m.update(readString) readBytes = len(readString) f.close() REVISION = m.hexdigest() def process_tokens(tokens): accu = [] prev = tokenize.NEWLINE indent = 0 line_buf = [] for (type, token, start, end, line) in tokens: token = token.replace('\r\n', '\n') if type == tokenize.NEWLINE: if line_buf: accu.append(indent * '\t') ln = "".join(line_buf) if ln == 'if __name__=="__main__":': break #ln = ln.replace('\n', '') accu.append(ln) accu.append('\n') line_buf = [] prev = tokenize.NEWLINE elif type == tokenize.INDENT: indent += 1 elif type == tokenize.DEDENT: indent -= 1 elif type == tokenize.NAME: if prev == tokenize.NAME or prev == tokenize.NUMBER: line_buf.append(' ') line_buf.append(token) elif type == tokenize.NUMBER: if prev == tokenize.NAME or prev == tokenize.NUMBER: line_buf.append(' ') line_buf.append(token) elif type == tokenize.STRING: if not line_buf and token.startswith('"'): pass else: line_buf.append(token) elif type == tokenize.COMMENT: pass elif type == tokenize.OP: line_buf.append(token) else: if token != "\n": line_buf.append(token) if token != '\n': prev = type body = "".join(accu) return body deco_re = re.compile('(def|class)\\s+(\w+)\\(.*') def process_decorators(body): lst = body.split('\n') accu = [] all_deco = [] buf = [] # put the decorator lines for line in lst: if line.startswith('@'): buf.append(line[1:]) elif buf: name = deco_re.sub('\\2', line) if not name: raise IOError("decorator not followed by a function!" + line) for x in buf: all_deco.append("%s(%s)" % (x, name)) accu.append(line) buf = [] else: accu.append(line) return "\n".join(accu+all_deco) def sfilter(path): if path.endswith('.py') : if Options.options.strip_comments: if sys.version_info[0] >= 3: f = open(path, "rb") try: tk = tokenize.tokenize(f.readline) next(tk) # the first one is always tokenize.ENCODING for Python 3, ignore it cnt = process_tokens(tk) finally: f.close() else: f = open(path, "r") try: cnt = process_tokens(tokenize.generate_tokens(f.readline)) finally: f.close() else: f = open(path, "r") try: cnt = f.read() finally: f.close() # WARNING: since we now require python 2.4, we do not process the decorators anymore # if you need such a thing, uncomment the code below: #cnt = process_decorators(cnt) #if cnt.find('set(') > -1: # cnt = 'import sys\nif sys.hexversion < 0x020400f0: from sets import Set as set\n' + cnt cnt = '#! /usr/bin/env python\n# encoding: utf-8\n# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file\n\n' + cnt else: f = open(path, "r") try: cnt = f.read() finally: f.close() if sys.hexversion > 0x030000f0: return (io.BytesIO(cnt.encode('utf-8')), len(cnt), cnt) return (io.BytesIO(cnt), len(cnt), cnt) def create_waf(*k, **kw): mw = 'tmp-waf-'+VERSION print("-> preparing %r" % mw) import tarfile, re zipType = Options.options.zip.strip().lower() if zipType not in zip_types: zipType = zip_types[0] #open a file as tar.[extension] for writing tar = tarfile.open('%s.tar.%s' % (mw, zipType), "w:%s" % zipType) files = [] add3rdparty = [] for x in Options.options.add3rdparty.split(','): if os.path.isabs(x): files.append(x) else: add3rdparty.append(x + '.py') for d in '. Tools extras'.split(): dd = os.path.join('waflib', d) for k in os.listdir(dd): if k == '__init__.py': files.append(os.path.join(dd, k)) continue if d == 'extras': if not k in add3rdparty: continue if k.endswith('.py'): files.append(os.path.join(dd, k)) for x in files: tarinfo = tar.gettarinfo(x, x) tarinfo.uid = tarinfo.gid = 0 tarinfo.uname = tarinfo.gname = 'root' (code, size, cnt) = sfilter(x) tarinfo.size = size if os.path.isabs(x): tarinfo.name = 'waflib/extras/' + os.path.split(x)[1] tar.addfile(tarinfo, code) tar.close() f = open('waf-light', 'rU') try: code1 = f.read() finally: f.close() # now store the revision unique number in waf #compute_revision() #reg = re.compile('^REVISION=(.*)', re.M) #code1 = reg.sub(r'REVISION="%s"' % REVISION, code1) code1 = code1.replace("if sys.hexversion<0x206000f:\n\traise ImportError('Python >= 2.6 is required to create the waf file')\n", '') code1 = code1.replace('\t#import waflib.extras.compat15#PRELUDE', Options.options.prelude) prefix = '' reg = re.compile('^INSTALL=(.*)', re.M) code1 = reg.sub(r'INSTALL=%r' % prefix, code1) #change the tarfile extension in the waf script reg = re.compile('bz2', re.M) code1 = reg.sub(zipType, code1) if zipType == 'gz': code1 = code1.replace('bunzip2', 'gzip -d') f = open('%s.tar.%s' % (mw, zipType), 'rb') try: cnt = f.read() finally: f.close() # the REVISION value is the md5 sum of the binary blob (facilitate audits) m = md5() m.update(cnt) REVISION = m.hexdigest() reg = re.compile('^REVISION=(.*)', re.M) code1 = reg.sub(r'REVISION="%s"' % REVISION, code1) def find_unused(kd, ch): for i in range(35, 125): for j in range(35, 125): if i==j: continue if i == 39 or j == 39: continue if i == 92 or j == 92: continue s = chr(i) + chr(j) if -1 == kd.find(s.encode()): return (kd.replace(ch.encode(), s.encode()), s) raise # The reverse order prevent collisions (cnt, C2) = find_unused(cnt, '\r') (cnt, C1) = find_unused(cnt, '\n') ccc = code1.replace("C1='x'", "C1='%s'" % C1).replace("C2='x'", "C2='%s'" % C2) f = open('waf', 'wb') try: f.write(ccc.encode()) f.write(to_bytes('#==>\n#')) f.write(cnt) f.write(to_bytes('\n#<==\n')) finally: f.close() if sys.platform == 'win32' or Options.options.make_batch: f = open('waf.bat', 'w') try: f.write('@python -x "%~dp0waf" %* & exit /b\n') finally: f.close() if sys.platform != 'win32': os.chmod('waf', Utils.O755) os.unlink('%s.tar.%s' % (mw, zipType)) def make_copy(inf, outf): (a, b, cnt) = sfilter(inf) f = open(outf, "wb") try: f.write(cnt) finally: f.close() def configure(conf): conf.load('python') conf.check_python_version((2,4)) def build(bld): waf = bld.path.make_node('waf') # create the node right here bld(name='create_waf', rule=create_waf, target=waf, always=True, color='PINK', update_outputs=True) debian/waf-1.7/README0000664000000000000000000000310612145745420011134 0ustar WHAT YOU WILL FIND HERE ----------------------- Waf (1.7) For the manual: http://docs.waf.googlecode.com/git/book_16/single.html For the api docs: http://docs.waf.googlecode.com/git/apidocs_16/index.html For the examples: see the folder demos/ HOW TO CREATE THE WAF SCRIPT ---------------------------- Python 2.6, 2.7, 3.0, 3.1 or 3.2 is required to generate the waf script. Execute: $ ./waf-light configure build Or, if you have several python versions installed: $ python3 ./waf-light configure build The Waf tools in waflib/extras are not added to the waf script. To add some of them, use the --tools switch: $ ./waf-light --tools=compat15,swig To add a tool that does not exist in the folder extras, pass an absolute path, and to customize the initialization, pass the parameter 'prelude'. Here is for example how to create a waf file using the compat15 module: $ ./waf-light --tools=compat15 --prelude=$'\tfrom waflib.extras import compat15\n' Any kind of initialization is possible, though one may prefer the build system kit (folder build_system_kit): $ ./waf-light --make-waf --tools=compat15,/comp/waf/aba.py --prelude=$'\tfrom waflib.extras import compat15\n\tprint "ok"' HOW TO TRY THE EXAMPLES ----------------------- Try this: $ cp waf demos/c/ $ cd demos/c/ $ ./waf configure build USING GIT --------- $ git clone https://code.google.com/p/waf/ set $HOME/.netrc to read: machine code.google.com login user@gmail.com password pass $ git remote add code https://code.google.com/p/waf.docs/ ... make a few changes $ git push code --------------------------- Thomas Nagy, 2012 (ita) debian/waf-1.7/waflib/0000775000000000000000000000000012253225221011510 5ustar debian/waf-1.7/waflib/Options.py0000664000000000000000000001730712145745420013535 0ustar #!/usr/bin/env python # encoding: utf-8 # Scott Newton, 2005 (scottn) # Thomas Nagy, 2006-2010 (ita) """ Support for waf command-line options Provides default command-line options, as well as custom ones, used by the ``options`` wscript function. """ import os, tempfile, optparse, sys, re from waflib import Logs, Utils, Context cmds = 'distclean configure build install clean uninstall check dist distcheck'.split() """ Constant representing the default waf commands displayed in:: $ waf --help """ options = {} """ A dictionary representing the command-line options:: $ waf --foo=bar """ commands = [] """ List of commands to execute extracted from the command-line. This list is consumed during the execution, see :py:func:`waflib.Scripting.run_commands`. """ lockfile = os.environ.get('WAFLOCK', '.lock-waf_%s_build' % sys.platform) try: cache_global = os.path.abspath(os.environ['WAFCACHE']) except KeyError: cache_global = '' platform = Utils.unversioned_sys_platform() class opt_parser(optparse.OptionParser): """ Command-line options parser. """ def __init__(self, ctx): optparse.OptionParser.__init__(self, conflict_handler="resolve", version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION)) self.formatter.width = Logs.get_term_cols() p = self.add_option self.ctx = ctx jobs = ctx.jobs() p('-j', '--jobs', dest='jobs', default=jobs, type='int', help='amount of parallel jobs (%r)' % jobs) p('-k', '--keep', dest='keep', default=0, action='count', help='keep running happily even if errors are found') p('-v', '--verbose', dest='verbose', default=0, action='count', help='verbosity level -v -vv or -vvv [default: 0]') p('--nocache', dest='nocache', default=False, action='store_true', help='ignore the WAFCACHE (if set)') p('--zones', dest='zones', default='', action='store', help='debugging zones (task_gen, deps, tasks, etc)') gr = optparse.OptionGroup(self, 'configure options') self.add_option_group(gr) gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') default_prefix = os.environ.get('PREFIX') if not default_prefix: if platform == 'win32': d = tempfile.gettempdir() default_prefix = d[0].upper() + d[1:] # win32 preserves the case, but gettempdir does not else: default_prefix = '/usr/local/' gr.add_option('--prefix', dest='prefix', default=default_prefix, help='installation prefix [default: %r]' % default_prefix) gr.add_option('--download', dest='download', default=False, action='store_true', help='try to download the tools if missing') gr = optparse.OptionGroup(self, 'build and install options') self.add_option_group(gr) gr.add_option('-p', '--progress', dest='progress_bar', default=0, action='count', help= '-p: progress bar; -pp: ide output') gr.add_option('--targets', dest='targets', default='', action='store', help='task generators, e.g. "target1,target2"') gr = optparse.OptionGroup(self, 'step options') self.add_option_group(gr) gr.add_option('--files', dest='files', default='', action='store', help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') default_destdir = os.environ.get('DESTDIR', '') gr = optparse.OptionGroup(self, 'install/uninstall options') self.add_option_group(gr) gr.add_option('--destdir', help='installation root [default: %r]' % default_destdir, default=default_destdir, dest='destdir') gr.add_option('-f', '--force', dest='force', default=False, action='store_true', help='force file installation') gr.add_option('--distcheck-args', help='arguments to pass to distcheck', default=None, action='store') def get_usage(self): """ Return the message to print on ``waf --help`` """ cmds_str = {} for cls in Context.classes: if not cls.cmd or cls.cmd == 'options': continue s = cls.__doc__ or '' cmds_str[cls.cmd] = s if Context.g_module: for (k, v) in Context.g_module.__dict__.items(): if k in ['options', 'init', 'shutdown']: continue if type(v) is type(Context.create_context): if v.__doc__ and not k.startswith('_'): cmds_str[k] = v.__doc__ just = 0 for k in cmds_str: just = max(just, len(k)) lst = [' %s: %s' % (k.ljust(just), v) for (k, v) in cmds_str.items()] lst.sort() ret = '\n'.join(lst) return '''waf [commands] [options] Main commands (example: ./waf build -j4) %s ''' % ret class OptionsContext(Context.Context): """ Collect custom options from wscript files and parses the command line. Set the global :py:const:`waflib.Options.commands` and :py:const:`waflib.Options.options` values. """ cmd = 'options' fun = 'options' def __init__(self, **kw): super(OptionsContext, self).__init__(**kw) self.parser = opt_parser(self) """Instance of :py:class:`waflib.Options.opt_parser`""" self.option_groups = {} def jobs(self): """ Find the amount of cpu cores to set the default amount of tasks executed in parallel. At runtime the options can be obtained from :py:const:`waflib.Options.options` :: from waflib.Options import options njobs = options.jobs :return: the amount of cpu cores :rtype: int """ count = int(os.environ.get('JOBS', 0)) if count < 1: if 'NUMBER_OF_PROCESSORS' in os.environ: # on Windows, use the NUMBER_OF_PROCESSORS environment variable count = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) else: # on everything else, first try the POSIX sysconf values if hasattr(os, 'sysconf_names'): if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_ONLN')) elif 'SC_NPROCESSORS_CONF' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_CONF')) if not count and os.name not in ('nt', 'java'): try: tmp = self.cmd_and_log(['sysctl', '-n', 'hw.ncpu'], quiet=0) except Exception: pass else: if re.match('^[0-9]+$', tmp): count = int(tmp) if count < 1: count = 1 elif count > 1024: count = 1024 return count def add_option(self, *k, **kw): """ Wrapper for optparse.add_option:: def options(ctx): ctx.add_option('-u', '--use', dest='use', default=False, action='store_true', help='a boolean option') """ return self.parser.add_option(*k, **kw) def add_option_group(self, *k, **kw): """ Wrapper for optparse.add_option_group:: def options(ctx): gr = ctx.add_option_group('some options') gr.add_option('-u', '--use', dest='use', default=False, action='store_true') """ try: gr = self.option_groups[k[0]] except KeyError: gr = self.parser.add_option_group(*k, **kw) self.option_groups[k[0]] = gr return gr def get_option_group(self, opt_str): """ Wrapper for optparse.get_option_group:: def options(ctx): gr = ctx.get_option_group('configure options') gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') """ try: return self.option_groups[opt_str] except KeyError: for group in self.parser.option_groups: if group.title == opt_str: return group return None def parse_args(self, _args=None): """ Parse arguments from a list (not bound to the command-line). :param _args: arguments :type _args: list of strings """ global options, commands (options, leftover_args) = self.parser.parse_args(args=_args) commands = leftover_args if options.destdir: options.destdir = os.path.abspath(os.path.expanduser(options.destdir)) if options.verbose >= 1: self.load('errcheck') def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ super(OptionsContext, self).execute() self.parse_args() debian/waf-1.7/waflib/Task.py0000664000000000000000000010337412145745420013004 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Tasks represent atomic operations such as processes. """ import os, shutil, re, tempfile from waflib import Utils, Logs, Errors # task states NOT_RUN = 0 """The task was not executed yet""" MISSING = 1 """The task has been executed but the files have not been created""" CRASHED = 2 """The task execution returned a non-zero exit status""" EXCEPTION = 3 """An exception occured in the task execution""" SKIPPED = 8 """The task did not have to be executed""" SUCCESS = 9 """The task was successfully executed""" ASK_LATER = -1 """The task is not ready to be executed""" SKIP_ME = -2 """The task does not need to be executed""" RUN_ME = -3 """The task must be executed""" COMPILE_TEMPLATE_SHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld wd = getattr(tsk, 'cwd', None) p = env.get_flat tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s return tsk.exec_command(cmd, cwd=wd, env=env.env or None) ''' COMPILE_TEMPLATE_NOSHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld wd = getattr(tsk, 'cwd', None) def to_list(xx): if isinstance(xx, str): return [xx] return xx tsk.last_cmd = lst = [] %s lst = [x for x in lst if x] return tsk.exec_command(lst, cwd=wd, env=env.env or None) ''' def cache_outputs(cls): """ Task class decorator applied to all task classes by default unless they define the attribute 'nocache':: from waflib import Task class foo(Task.Task): nocache = True If bld.cache_global is defined and if the task instances produces output nodes, the files will be copied into a folder in the cache directory The files may also be retrieved from that folder, if it exists """ m1 = cls.run def run(self): bld = self.generator.bld if bld.cache_global and not bld.nocache: if self.can_retrieve_cache(): return 0 return m1(self) cls.run = run m2 = cls.post_run def post_run(self): bld = self.generator.bld ret = m2(self) if bld.cache_global and not bld.nocache: self.put_files_cache() return ret cls.post_run = post_run return cls classes = {} "class tasks created by user scripts or Waf tools are kept in this dict name -> class object" class store_task_type(type): """ Metaclass: store the task classes into :py:const:`waflib.Task.classes`, or to the dict pointed by the class attribute 'register'. The attribute 'run_str' will be processed to compute a method 'run' on the task class The decorator :py:func:`waflib.Task.cache_outputs` is also applied to the class """ def __init__(cls, name, bases, dict): super(store_task_type, cls).__init__(name, bases, dict) name = cls.__name__ if name.endswith('_task'): name = name.replace('_task', '') if name != 'evil' and name != 'TaskBase': global classes if getattr(cls, 'run_str', None): # if a string is provided, convert it to a method (f, dvars) = compile_fun(cls.run_str, cls.shell) cls.hcode = cls.run_str cls.run_str = None cls.run = f cls.vars = list(set(cls.vars + dvars)) cls.vars.sort() elif getattr(cls, 'run', None) and not 'hcode' in cls.__dict__: # getattr(cls, 'hcode') would look in the upper classes cls.hcode = Utils.h_fun(cls.run) if not getattr(cls, 'nocache', None): cls = cache_outputs(cls) # be creative getattr(cls, 'register', classes)[name] = cls evil = store_task_type('evil', (object,), {}) "Base class provided to avoid writing a metaclass, so the code can run in python 2.6 and 3.x unmodified" class TaskBase(evil): """ Base class for all Waf tasks, which should be seen as an interface. For illustration purposes, instances of this class will execute the attribute 'fun' in :py:meth:`waflib.Task.TaskBase.run`. When in doubt, create subclasses of :py:class:`waflib.Task.Task` instead. Subclasses should override these methods: #. __str__: string to display to the user #. runnable_status: ask the task if it should be run, skipped, or if we have to ask later #. run: let threads execute the task #. post_run: let threads update the data regarding the task (cache) """ color = 'GREEN' """Color for the console display, see :py:const:`waflib.Logs.colors_lst`""" ext_in = [] """File extensions that objects of this task class might use""" ext_out = [] """File extensions that objects of this task class might create""" before = [] """List of task class names to execute before instances of this class""" after = [] """List of task class names to execute after instances of this class""" hcode = '' """String representing an additional hash for the class representation""" def __init__(self, *k, **kw): """ The base task class requires a task generator, which will be itself if missing """ self.hasrun = NOT_RUN try: self.generator = kw['generator'] except KeyError: self.generator = self def __repr__(self): "for debugging purposes" return '\n\t{task %r: %s %s}' % (self.__class__.__name__, id(self), str(getattr(self, 'fun', ''))) def __str__(self): "string to display to the user" if hasattr(self, 'fun'): return 'executing: %s\n' % self.fun.__name__ return self.__class__.__name__ + '\n' def __hash__(self): "Very fast hashing scheme but not persistent (replace/implement in subclasses and see :py:meth:`waflib.Task.Task.uid`)" return id(self) def exec_command(self, cmd, **kw): """ Wrapper for :py:meth:`waflib.Context.Context.exec_command` which sets a current working directory to ``build.variant_dir`` :return: the return code :rtype: int """ bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir return bld.exec_command(cmd, **kw) def runnable_status(self): """ State of the task :return: a task state in :py:const:`waflib.Task.RUN_ME`, :py:const:`waflib.Task.SKIP_ME` or :py:const:`waflib.Task.ASK_LATER`. :rtype: int """ return RUN_ME def process(self): """ Assume that the task has had a new attribute ``master`` which is an instance of :py:class:`waflib.Runner.Parallel`. Execute the task and then put it back in the queue :py:attr:`waflib.Runner.Parallel.out` (may be replaced by subclassing). """ m = self.master if m.stop: m.out.put(self) return # remove the task signature immediately before it is executed # in case of failure the task will be executed again try: del self.generator.bld.task_sigs[self.uid()] except KeyError: pass try: self.generator.bld.returned_tasks.append(self) self.log_display(self.generator.bld) ret = self.run() except Exception: self.err_msg = Utils.ex_stack() self.hasrun = EXCEPTION # TODO cleanup m.error_handler(self) m.out.put(self) return if ret: self.err_code = ret self.hasrun = CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = Utils.ex_stack() self.hasrun = EXCEPTION else: self.hasrun = SUCCESS if self.hasrun != SUCCESS: m.error_handler(self) m.out.put(self) def run(self): """ Called by threads to execute the tasks. The default is empty and meant to be overridden in subclasses. It is a bad idea to create nodes in this method (so, no node.ant_glob) :rtype: int """ if hasattr(self, 'fun'): return self.fun(self) return 0 def post_run(self): "Update the cache files (executed by threads). Override in subclasses." pass def log_display(self, bld): "Write the execution status on the context logger" bld.to_log(self.display()) def display(self): """ Return an execution status for the console, the progress bar, or the IDE output. :rtype: string """ col1 = Logs.colors(self.color) col2 = Logs.colors.NORMAL master = self.master def cur(): # the current task position, computed as late as possible tmp = -1 if hasattr(master, 'ready'): tmp -= master.ready.qsize() return master.processed + tmp if self.generator.bld.progress_bar == 1: return self.generator.bld.progress_line(cur(), master.total, col1, col2) if self.generator.bld.progress_bar == 2: ela = str(self.generator.bld.timer) try: ins = ','.join([n.name for n in self.inputs]) except AttributeError: ins = '' try: outs = ','.join([n.name for n in self.outputs]) except AttributeError: outs = '' return '|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n' % (master.total, cur(), ins, outs, ela) s = str(self) if not s: return None total = master.total n = len(str(total)) fs = '[%%%dd/%%%dd] %%s%%s%%s' % (n, n) return fs % (cur(), total, col1, s, col2) def attr(self, att, default=None): """ Retrieve an attribute from the instance or from the class. :param att: variable name :type att: string :param default: default value """ ret = getattr(self, att, self) if ret is self: return getattr(self.__class__, att, default) return ret def hash_constraints(self): """ Identify a task type for all the constraints relevant for the scheduler: precedence, file production :return: a hash value :rtype: string """ cls = self.__class__ tup = (str(cls.before), str(cls.after), str(cls.ext_in), str(cls.ext_out), cls.__name__, cls.hcode) h = hash(tup) return h def format_error(self): """ Error message to display to the user when a build fails :rtype: string """ msg = getattr(self, 'last_cmd', '') name = getattr(self.generator, 'name', '') if getattr(self, "err_msg", None): return self.err_msg elif not self.hasrun: return 'task in %r was not executed for some reason: %r' % (name, self) elif self.hasrun == CRASHED: try: return ' -> task in %r failed (exit status %r): %r\n%r' % (name, self.err_code, self, msg) except AttributeError: return ' -> task in %r failed: %r\n%r' % (name, self, msg) elif self.hasrun == MISSING: return ' -> missing files in %r: %r\n%r' % (name, self, msg) else: return 'invalid status for task in %r: %r' % (name, self.hasrun) def colon(self, var1, var2): """ private function for the moment used for scriptlet expressions such as ${FOO_ST:FOO}, for example, if env.FOO_ST = ['-a', '-b'] env.FOO = ['1', '2'] then the result will be ['-a', '-b', '1', '-a', '-b', '2'] """ tmp = self.env[var1] if isinstance(var2, str): it = self.env[var2] else: it = var2 if isinstance(tmp, str): return [tmp % x for x in it] else: if Logs.verbose and not tmp and it: Logs.warn('Missing env variable %r for task %r (generator %r)' % (var1, self, self.generator)) lst = [] for y in it: lst.extend(tmp) lst.append(y) return lst class Task(TaskBase): """ This class deals with the filesystem (:py:class:`waflib.Node.Node`). The method :py:class:`waflib.Task.Task.runnable_status` uses a hash value (from :py:class:`waflib.Task.Task.signature`) which is persistent from build to build. When the value changes, the task has to be executed. The method :py:class:`waflib.Task.Task.post_run` will assign the task signature to the output nodes (if present). """ vars = [] """Variables to depend on (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" shell = False """Execute the command with the shell (class attribute)""" def __init__(self, *k, **kw): TaskBase.__init__(self, *k, **kw) self.env = kw['env'] """ConfigSet object (make sure to provide one)""" self.inputs = [] """List of input nodes, which represent the files used by the task instance""" self.outputs = [] """List of output nodes, which represent the files created by the task instance""" self.dep_nodes = [] """List of additional nodes to depend on""" self.run_after = set([]) """Set of tasks that must be executed before this one""" # Additionally, you may define the following #self.dep_vars = 'PREFIX DATADIR' def __str__(self): "string to display to the user" env = self.env src_str = ' '.join([a.nice_path() for a in self.inputs]) tgt_str = ' '.join([a.nice_path() for a in self.outputs]) if self.outputs: sep = ' -> ' else: sep = '' return '%s: %s%s%s\n' % (self.__class__.__name__.replace('_task', ''), src_str, sep, tgt_str) def __repr__(self): "for debugging purposes" try: ins = ",".join([x.name for x in self.inputs]) outs = ",".join([x.name for x in self.outputs]) except AttributeError: ins = ",".join([str(x) for x in self.inputs]) outs = ",".join([str(x) for x in self.outputs]) return "".join(['\n\t{task %r: ' % id(self), self.__class__.__name__, " ", ins, " -> ", outs, '}']) def uid(self): """ Return an identifier used to determine if tasks are up-to-date. Since the identifier will be stored between executions, it must be: - unique: no two tasks return the same value (for a given build context) - the same for a given task instance By default, the node paths, the class name, and the function are used as inputs to compute a hash. The pointer to the object (python built-in 'id') will change between build executions, and must be avoided in such hashes. :return: hash value :rtype: string """ try: return self.uid_ except AttributeError: # this is not a real hot zone, but we want to avoid surprises here m = Utils.md5() up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.abspath().encode()) self.uid_ = m.digest() return self.uid_ def set_inputs(self, inp): """ Append the nodes to the *inputs* :param inp: input nodes :type inp: node or list of nodes """ if isinstance(inp, list): self.inputs += inp else: self.inputs.append(inp) def set_outputs(self, out): """ Append the nodes to the *outputs* :param out: output nodes :type out: node or list of nodes """ if isinstance(out, list): self.outputs += out else: self.outputs.append(out) def set_run_after(self, task): """ Run this task only after *task*. Affect :py:meth:`waflib.Task.runnable_status` You probably want to use tsk.run_after.add(task) directly :param task: task :type task: :py:class:`waflib.Task.Task` """ assert isinstance(task, TaskBase) self.run_after.add(task) def signature(self): """ Task signatures are stored between build executions, they are use to track the changes made to the input nodes (not to the outputs!). The signature hashes data from various sources: * explicit dependencies: files listed in the inputs (list of node objects) :py:meth:`waflib.Task.Task.sig_explicit_deps` * implicit dependencies: list of nodes returned by scanner methods (when present) :py:meth:`waflib.Task.Task.sig_implicit_deps` * hashed data: variables/values read from task.__class__.vars/task.env :py:meth:`waflib.Task.Task.sig_vars` If the signature is expected to give a different result, clear the cache kept in ``self.cache_sig``:: from waflib import Task class cls(Task.Task): def signature(self): sig = super(Task.Task, self).signature() delattr(self, 'cache_sig') return super(Task.Task, self).signature() """ try: return self.cache_sig except AttributeError: pass self.m = Utils.md5() self.m.update(self.hcode.encode()) # explicit deps self.sig_explicit_deps() # env vars self.sig_vars() # implicit deps / scanner results if self.scan: try: self.sig_implicit_deps() except Errors.TaskRescan: return self.signature() ret = self.cache_sig = self.m.digest() return ret def runnable_status(self): """ Override :py:meth:`waflib.Task.TaskBase.runnable_status` to determine if the task is ready to be run (:py:attr:`waflib.Task.Task.run_after`) """ #return 0 # benchmarking for t in self.run_after: if not t.hasrun: return ASK_LATER bld = self.generator.bld # first compute the signature try: new_sig = self.signature() except Errors.TaskNotReady: return ASK_LATER # compare the signature to a signature computed previously key = self.uid() try: prev_sig = bld.task_sigs[key] except KeyError: Logs.debug("task: task %r must run as it was never run before or the task code changed" % self) return RUN_ME # compare the signatures of the outputs for node in self.outputs: try: if node.sig != new_sig: return RUN_ME except AttributeError: Logs.debug("task: task %r must run as the output nodes do not exist" % self) return RUN_ME if new_sig != prev_sig: return RUN_ME return SKIP_ME def post_run(self): """ Called after successful execution to update the cache data :py:class:`waflib.Node.Node` sigs and :py:attr:`waflib.Build.BuildContext.task_sigs`. The node signature is obtained from the task signature, but the output nodes may also get the signature of their contents. See the class decorator :py:func:`waflib.Task.update_outputs` if you need this behaviour. """ bld = self.generator.bld sig = self.signature() for node in self.outputs: # check if the node exists .. try: os.stat(node.abspath()) except OSError: self.hasrun = MISSING self.err_msg = '-> missing file: %r' % node.abspath() raise Errors.WafError(self.err_msg) # important, store the signature for the next run node.sig = sig bld.task_sigs[self.uid()] = self.cache_sig def sig_explicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature`, hash :py:attr:`waflib.Task.Task.inputs` and :py:attr:`waflib.Task.Task.dep_nodes` signatures. :rtype: hash value """ bld = self.generator.bld upd = self.m.update # the inputs for x in self.inputs + self.dep_nodes: try: upd(x.get_bld_sig()) except (AttributeError, TypeError): raise Errors.WafError('Missing node signature for %r (required by %r)' % (x, self)) # manual dependencies, they can slow down the builds if bld.deps_man: additional_deps = bld.deps_man for x in self.inputs + self.outputs: try: d = additional_deps[id(x)] except KeyError: continue for v in d: if isinstance(v, bld.root.__class__): try: v = v.get_bld_sig() except AttributeError: raise Errors.WafError('Missing node signature for %r (required by %r)' % (v, self)) elif hasattr(v, '__call__'): v = v() # dependency is a function, call it upd(v) return self.m.digest() def sig_vars(self): """ Used by :py:meth:`waflib.Task.Task.signature`, hash :py:attr:`waflib.Task.Task.env` variables/values :rtype: hash value """ bld = self.generator.bld env = self.env upd = self.m.update # dependencies on the environment vars act_sig = bld.hash_env_vars(env, self.__class__.vars) upd(act_sig) # additional variable dependencies, if provided dep_vars = getattr(self, 'dep_vars', None) if dep_vars: upd(bld.hash_env_vars(env, dep_vars)) return self.m.digest() scan = None """ This method, when provided, returns a tuple containing: * a list of nodes corresponding to real files * a list of names for files not found in path_lst For example:: from waflib.Task import Task class mytask(Task): def scan(self, node): return ((), ()) The first and second lists are stored in :py:attr:`waflib.Build.BuildContext.node_deps` and :py:attr:`waflib.Build.BuildContext.raw_deps` respectively. """ def sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature` hashes node signatures obtained by scanning for dependencies (:py:meth:`waflib.Task.Task.scan`). The exception :py:class:`waflib.Errors.TaskRescan` is thrown when a file has changed. When this occurs, :py:meth:`waflib.Task.Task.signature` is called once again, and this method will be executed once again, this time calling :py:meth:`waflib.Task.Task.scan` for searching the dependencies. :rtype: hash value """ bld = self.generator.bld # get the task signatures from previous runs key = self.uid() prev = bld.task_sigs.get((key, 'imp'), []) # for issue #379 if prev: try: if prev == self.compute_sig_implicit_deps(): return prev except Exception: # when a file was renamed (IOError usually), remove the stale nodes (headers in folders without source files) # this will break the order calculation for headers created during the build in the source directory (should be uncommon) # the behaviour will differ when top != out for x in bld.node_deps.get(self.uid(), []): if x.is_child_of(bld.srcnode): try: os.stat(x.abspath()) except OSError: try: del x.parent.children[x.name] except KeyError: pass del bld.task_sigs[(key, 'imp')] raise Errors.TaskRescan('rescan') # no previous run or the signature of the dependencies has changed, rescan the dependencies (nodes, names) = self.scan() if Logs.verbose: Logs.debug('deps: scanner for %s returned %s %s' % (str(self), str(nodes), str(names))) # store the dependencies in the cache bld.node_deps[key] = nodes bld.raw_deps[key] = names # might happen self.are_implicit_nodes_ready() # recompute the signature and return it try: bld.task_sigs[(key, 'imp')] = sig = self.compute_sig_implicit_deps() except Exception: if Logs.verbose: for k in bld.node_deps.get(self.uid(), []): try: k.get_bld_sig() except Exception: Logs.warn('Missing signature for node %r (may cause rebuilds)' % k) else: return sig def compute_sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.sig_implicit_deps` for computing the actual hash of the :py:class:`waflib.Node.Node` returned by the scanner. :return: hash value :rtype: string """ upd = self.m.update bld = self.generator.bld self.are_implicit_nodes_ready() # scanner returns a node that does not have a signature # just *ignore* the error and let them figure out from the compiler output # waf -k behaviour for k in bld.node_deps.get(self.uid(), []): upd(k.get_bld_sig()) return self.m.digest() def are_implicit_nodes_ready(self): """ For each node returned by the scanner, see if there is a task behind it, and force the build order The performance impact on null builds is nearly invisible (1.66s->1.86s), but this is due to agressive caching (1.86s->28s) """ bld = self.generator.bld try: cache = bld.dct_implicit_nodes except AttributeError: bld.dct_implicit_nodes = cache = {} try: dct = cache[bld.cur] except KeyError: dct = cache[bld.cur] = {} for tsk in bld.cur_tasks: for x in tsk.outputs: dct[x] = tsk modified = False for x in bld.node_deps.get(self.uid(), []): if x in dct: self.run_after.add(dct[x]) modified = True if modified: for tsk in self.run_after: if not tsk.hasrun: #print "task is not ready..." raise Errors.TaskNotReady('not ready') def can_retrieve_cache(self): """ Used by :py:meth:`waflib.Task.cache_outputs` Retrieve build nodes from the cache update the file timestamps to help cleaning the least used entries from the cache additionally, set an attribute 'cached' to avoid re-creating the same cache files Suppose there are files in `cache/dir1/file1` and `cache/dir2/file2`: #. read the timestamp of dir1 #. try to copy the files #. look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) #. should an exception occur, ignore the data """ if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) # first try to access the cache folder for the task dname = os.path.join(self.generator.bld.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None for node in self.outputs: orig = os.path.join(dname, node.name) try: shutil.copy2(orig, node.abspath()) # mark the cache file as used recently (modified) os.utime(orig, None) except (OSError, IOError): Logs.debug('task: failed retrieving file') return None # is it the same folder? try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: node.sig = sig if self.generator.bld.progress_bar < 1: self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True def put_files_cache(self): """ Used by :py:func:`waflib.Task.cache_outputs` to store the build files in the cache """ # file caching, if possible # try to avoid data corruption as much as possible if getattr(self, 'cached', None): return None if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=self.generator.bld.cache_global + os.sep + 'waf') try: shutil.rmtree(dname) except Exception: pass try: for node in self.outputs: dest = os.path.join(tmpdir, node.name) shutil.copy2(node.abspath(), dest) except (OSError, IOError): try: shutil.rmtree(tmpdir) except Exception: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except Exception: pass else: try: os.chmod(dname, Utils.O755) except Exception: pass def is_before(t1, t2): """ Return a non-zero value if task t1 is to be executed before task t2:: t1.ext_out = '.h' t2.ext_in = '.h' t2.after = ['t1'] t1.before = ['t2'] waflib.Task.is_before(t1, t2) # True :param t1: task :type t1: :py:class:`waflib.Task.TaskBase` :param t2: task :type t2: :py:class:`waflib.Task.TaskBase` """ to_list = Utils.to_list for k in to_list(t2.ext_in): if k in to_list(t1.ext_out): return 1 if t1.__class__.__name__ in to_list(t2.after): return 1 if t2.__class__.__name__ in to_list(t1.before): return 1 return 0 def set_file_constraints(tasks): """ Adds tasks to the task 'run_after' attribute based on the task inputs and outputs :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.TaskBase` """ ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) for x in tasks: for a in getattr(x, 'inputs', []) + getattr(x, 'dep_nodes', []): ins[id(a)].add(x) for a in getattr(x, 'outputs', []): outs[id(a)].add(x) links = set(ins.keys()).intersection(outs.keys()) for k in links: for a in ins[k]: a.run_after.update(outs[k]) def set_precedence_constraints(tasks): """ Add tasks to the task 'run_after' attribute based on the after/before/ext_out/ext_in attributes :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.TaskBase` """ cstr_groups = Utils.defaultdict(list) for x in tasks: h = x.hash_constraints() cstr_groups[h].append(x) keys = list(cstr_groups.keys()) maxi = len(keys) # this list should be short for i in range(maxi): t1 = cstr_groups[keys[i]][0] for j in range(i + 1, maxi): t2 = cstr_groups[keys[j]][0] # add the constraints based on the comparisons if is_before(t1, t2): a = i b = j elif is_before(t2, t1): a = j b = i else: continue aval = set(cstr_groups[keys[a]]) for x in cstr_groups[keys[b]]: x.run_after.update(aval) def funex(c): """ Compile a function by 'exec' :param c: function to compile :type c: string :return: the function 'f' declared in the input string :rtype: function """ dc = {} exec(c, dc) return dc['f'] reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})", re.M) def compile_fun_shell(line): """ Create a compiled function to execute a process with the shell WARNING: this method may disappear anytime, so use compile_fun instead """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return '\\\\' elif g('subst'): extr.append((g('var'), g('code'))); return "%s" return None line = reg_act.sub(repl, line) or line parm = [] dvars = [] app = parm.append for (var, meth) in extr: if var == 'SRC': if meth: app('tsk.inputs%s' % meth) else: app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])') elif var == 'TGT': if meth: app('tsk.outputs%s' % meth) else: app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])') elif meth: if meth.startswith(':'): m = meth[1:] if m == 'SRC': m = '[a.path_from(bld.bldnode) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(bld.bldnode) for a in tsk.outputs]' elif m[:3] not in ('tsk', 'gen', 'bld'): dvars.extend([var, meth[1:]]) m = '%r' % m app('" ".join(tsk.colon(%r, %s))' % (var, m)) else: app('%s%s' % (var, meth)) else: if not var in dvars: dvars.append(var) app("p('%s')" % var) if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) else: parm = '' c = COMPILE_TEMPLATE_SHELL % (line, parm) Logs.debug('action: %s' % c.strip().splitlines()) return (funex(c), dvars) def compile_fun_noshell(line): """ Create a compiled function to execute a process without the shell WARNING: this method may disappear anytime, so use compile_fun instead """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('subst'): extr.append((g('var'), g('code'))); return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) buf = [] dvars = [] app = buf.append for x in range(len(extr)): params[x] = params[x].strip() if params[x]: app("lst.extend(%r)" % params[x].split()) (var, meth) = extr[x] if var == 'SRC': if meth: app('lst.append(tsk.inputs%s)' % meth) else: app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])") elif var == 'TGT': if meth: app('lst.append(tsk.outputs%s)' % meth) else: app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])") elif meth: if meth.startswith(':'): m = meth[1:] if m == 'SRC': m = '[a.path_from(bld.bldnode) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(bld.bldnode) for a in tsk.outputs]' elif m[:3] not in ('tsk', 'gen', 'bld'): dvars.extend([var, m]) m = '%r' % m app('lst.extend(tsk.colon(%r, %s))' % (var, m)) else: app('lst.extend(gen.to_list(%s%s))' % (var, meth)) else: app('lst.extend(to_list(env[%r]))' % var) if not var in dvars: dvars.append(var) if extr: if params[-1]: app("lst.extend(%r)" % params[-1].split()) fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) Logs.debug('action: %s' % fun.strip().splitlines()) return (funex(fun), dvars) def compile_fun(line, shell=False): """ Parse a string expression such as "${CC} ${SRC} -o ${TGT}" and return a pair containing: * the function created (compiled) for use as :py:meth:`waflib.Task.TaskBase.run` * the list of variables that imply a dependency from self.env for example:: from waflib.Task import compile_fun compile_fun('cxx', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') def build(bld): bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') The env variables (CXX, ..) on the task must not hold dicts (order) The reserved keywords *TGT* and *SRC* represent the task input and output nodes """ if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: shell = True if shell: return compile_fun_shell(line) else: return compile_fun_noshell(line) def task_factory(name, func=None, vars=None, color='GREEN', ext_in=[], ext_out=[], before=[], after=[], shell=False, scan=None): """ Deprecated. Return a new task subclass with the function ``run`` compiled from the line given. Provided for compatibility with waf 1.4-1.5, when we did not have the metaclass to register new classes (will be removed in Waf 1.8) :param func: method run :type func: string or function :param vars: list of variables to hash :type vars: list of string :param color: color to use :type color: string :param shell: when *func* is a string, enable/disable the use of the shell :type shell: bool :param scan: method scan :type scan: function :rtype: :py:class:`waflib.Task.Task` """ params = { 'vars': vars or [], # function arguments are static, and this one may be modified by the class 'color': color, 'name': name, 'ext_in': Utils.to_list(ext_in), 'ext_out': Utils.to_list(ext_out), 'before': Utils.to_list(before), 'after': Utils.to_list(after), 'shell': shell, 'scan': scan, } if isinstance(func, str): params['run_str'] = func else: params['run'] = func cls = type(Task)(name, (Task,), params) global classes classes[name] = cls return cls def always_run(cls): """ Task class decorator Set all task instances of this class to be executed whenever a build is started The task signature is calculated, but the result of the comparation between task signatures is bypassed """ old = cls.runnable_status def always(self): ret = old(self) if ret == SKIP_ME: ret = RUN_ME return ret cls.runnable_status = always return cls def update_outputs(cls): """ Task class decorator If you want to create files in the source directory. For example, to keep *foo.txt* in the source directory, create it first and declare:: def build(bld): bld(rule='cp ${SRC} ${TGT}', source='wscript', target='foo.txt', update_outputs=True) """ old_post_run = cls.post_run def post_run(self): old_post_run(self) for node in self.outputs: node.sig = Utils.h_file(node.abspath()) self.generator.bld.task_sigs[node.abspath()] = self.uid() # issue #1017 cls.post_run = post_run old_runnable_status = cls.runnable_status def runnable_status(self): status = old_runnable_status(self) if status != RUN_ME: return status try: # by default, we check that the output nodes have the signature of the task # perform a second check, returning 'SKIP_ME' as we are expecting that # the signatures do not match bld = self.generator.bld prev_sig = bld.task_sigs[self.uid()] if prev_sig == self.signature(): for x in self.outputs: if not x.sig or bld.task_sigs[x.abspath()] != self.uid(): return RUN_ME return SKIP_ME except KeyError: pass except IndexError: pass except AttributeError: pass return RUN_ME cls.runnable_status = runnable_status return cls debian/waf-1.7/waflib/fixpy2.py0000664000000000000000000000253012145745420013313 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ burn a book, save a tree """ import os all_modifs = {} def fixdir(dir): """call all the substitution functions on the waf folders""" global all_modifs for k in all_modifs: for v in all_modifs[k]: modif(os.path.join(dir, 'waflib'), k, v) def modif(dir, name, fun): """execute a substitution function""" if name == '*': lst = [] for y in '. Tools extras'.split(): for x in os.listdir(os.path.join(dir, y)): if x.endswith('.py'): lst.append(y + os.sep + x) for x in lst: modif(dir, x, fun) return filename = os.path.join(dir, name) f = open(filename, 'r') try: txt = f.read() finally: f.close() txt = fun(txt) f = open(filename, 'w') try: f.write(txt) finally: f.close() def subst(*k): """register a substitution function""" def do_subst(fun): global all_modifs for x in k: try: all_modifs[x].append(fun) except KeyError: all_modifs[x] = [fun] return fun return do_subst @subst('*') def r1(code): "utf-8 fixes for python < 2.6" code = code.replace('as e:', ',e:') code = code.replace(".decode(sys.stdout.encoding or 'iso8859-1')", '') code = code.replace('.encode()', '') return code @subst('Runner.py') def r4(code): "generator syntax" code = code.replace('next(self.biter)', 'self.biter.next()') return code debian/waf-1.7/waflib/Errors.py0000664000000000000000000000321312145745420013345 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Exceptions used in the Waf code """ import traceback, sys class WafError(Exception): """Base class for all Waf errors""" def __init__(self, msg='', ex=None): """ :param msg: error message :type msg: string :param ex: exception causing this error (optional) :type ex: exception """ self.msg = msg assert not isinstance(msg, Exception) self.stack = [] if ex: if not msg: self.msg = str(ex) if isinstance(ex, WafError): self.stack = ex.stack else: self.stack = traceback.extract_tb(sys.exc_info()[2]) self.stack += traceback.extract_stack()[:-1] self.verbose_msg = ''.join(traceback.format_list(self.stack)) def __str__(self): return str(self.msg) class BuildError(WafError): """ Errors raised during the build and install phases """ def __init__(self, error_tasks=[]): """ :param error_tasks: tasks that could not complete normally :type error_tasks: list of task objects """ self.tasks = error_tasks WafError.__init__(self, self.format_error()) def format_error(self): """format the error messages from the tasks that failed""" lst = ['Build failed'] for tsk in self.tasks: txt = tsk.format_error() if txt: lst.append(txt) return '\n'.join(lst) class ConfigurationError(WafError): """ Configuration exception raised in particular by :py:meth:`waflib.Context.Context.fatal` """ pass class TaskRescan(WafError): """task-specific exception type, trigger a signature recomputation""" pass class TaskNotReady(WafError): """task-specific exception type, raised when the task signature cannot be computed""" pass debian/waf-1.7/waflib/Node.py0000664000000000000000000004577612145745420013002 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Node: filesystem structure, contains lists of nodes #. Each file/folder is represented by exactly one node. #. Some potential class properties are stored on :py:class:`waflib.Build.BuildContext` : nodes to depend on, etc. Unused class members can increase the `.wafpickle` file size sensibly. #. Node objects should never be created directly, use the methods :py:func:`Node.make_node` or :py:func:`Node.find_node` #. The methods :py:func:`Node.find_resource`, :py:func:`Node.find_dir` :py:func:`Node.find_or_declare` should be used when a build context is present #. Each instance of :py:class:`waflib.Context.Context` has a unique :py:class:`Node` subclass. (:py:class:`waflib.Node.Nod3`, see the :py:class:`waflib.Context.Context` initializer). A reference to the context owning a node is held as self.ctx """ import os, re, sys, shutil from waflib import Utils, Errors exclude_regs = ''' **/*~ **/#*# **/.#* **/%*% **/._* **/CVS **/CVS/** **/.cvsignore **/SCCS **/SCCS/** **/vssver.scc **/.svn **/.svn/** **/BitKeeper **/.git **/.git/** **/.gitignore **/.bzr **/.bzrignore **/.bzr/** **/.hg **/.hg/** **/_MTN **/_MTN/** **/.arch-ids **/{arch} **/_darcs **/_darcs/** **/.intlcache **/.DS_Store''' """ Ant patterns for files and folders to exclude while doing the recursive traversal in :py:meth:`waflib.Node.Node.ant_glob` """ def split_path(path): """ Split a path by os.sep (This is not os.path.split) :param path: path to split :type path: string :rtype: list of string :return: the path, split """ return path.split('/') def split_path_cygwin(path): if path.startswith('//'): ret = path.split('/')[2:] ret[0] = '/' + ret[0] return ret return path.split('/') re_sp = re.compile('[/\\\\]') def split_path_win32(path): if path.startswith('\\\\'): ret = re.split(re_sp, path)[2:] ret[0] = '\\' + ret[0] return ret return re.split(re_sp, path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif Utils.is_win32: split_path = split_path_win32 class Node(object): """ This class is organized in two parts * The basic methods meant for filesystem access (compute paths, create folders, etc) * The methods bound to a :py:class:`waflib.Build.BuildContext` (require ``bld.srcnode`` and ``bld.bldnode``) The Node objects are not thread safe in any way. """ __slots__ = ('name', 'sig', 'children', 'parent', 'cache_abspath', 'cache_isdir', 'cache_sig') def __init__(self, name, parent): self.name = name self.parent = parent if parent: if name in parent.children: raise Errors.WafError('node %s exists in the parent files %r already' % (name, parent)) parent.children[name] = self def __setstate__(self, data): "Deserializes from data" self.name = data[0] self.parent = data[1] if data[2] is not None: self.children = data[2] if data[3] is not None: self.sig = data[3] def __getstate__(self): "Serialize the node info" return (self.name, self.parent, getattr(self, 'children', None), getattr(self, 'sig', None)) def __str__(self): "String representation (name), for debugging purposes" return self.name def __repr__(self): "String representation (abspath), for debugging purposes" return self.abspath() def __hash__(self): "Node hash, used for storage in dicts. This hash is not persistent." return id(self) def __eq__(self, node): "Node comparison, based on the IDs" return id(self) == id(node) def __copy__(self): "Implemented to prevent nodes from being copied (raises an exception)" raise Errors.WafError('nodes are not supposed to be copied') def read(self, flags='r', encoding='ISO8859-1'): """ Return the contents of the file represented by this node:: def build(bld): bld.path.find_node('wscript').read() :type fname: string :param fname: Path to file :type m: string :param m: Open mode :rtype: string :return: File contents """ return Utils.readf(self.abspath(), flags, encoding) def write(self, data, flags='w', encoding='ISO8859-1'): """ Write some text to the physical file represented by this node:: def build(bld): bld.path.make_node('foo.txt').write('Hello, world!') :type data: string :param data: data to write :type flags: string :param flags: Write mode """ Utils.writef(self.abspath(), data, flags, encoding) def chmod(self, val): """ Change file/dir permissions:: def build(bld): bld.path.chmod(493) # 0755 """ os.chmod(self.abspath(), val) def delete(self): """Delete the file/folders, and remove this node from the tree. It becomes invalid after that""" try: if getattr(self, 'children', None): shutil.rmtree(self.abspath()) else: os.unlink(self.abspath()) except OSError: pass self.evict() def evict(self): """Internal - called when a node is removed""" del self.parent.children[self.name] def suffix(self): """Return the file extension""" k = max(0, self.name.rfind('.')) return self.name[k:] def height(self): """Depth in the folder hierarchy from the filesystem root or from all the file drives""" d = self val = -1 while d: d = d.parent val += 1 return val def listdir(self): """List the folder contents""" lst = Utils.listdir(self.abspath()) lst.sort() return lst def mkdir(self): """ Create a folder represented by this node, creating intermediate nodes as needed An exception will be raised only when the folder cannot possibly exist there """ if getattr(self, 'cache_isdir', None): return try: self.parent.mkdir() except OSError: pass if self.name: try: os.makedirs(self.abspath()) except OSError: pass if not os.path.isdir(self.abspath()): raise Errors.WafError('Could not create the directory %s' % self.abspath()) try: self.children except AttributeError: self.children = {} self.cache_isdir = True def find_node(self, lst): """ Find a node on the file system (files or folders), create intermediate nodes as needed :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur continue try: ch = cur.children except AttributeError: cur.children = {} else: try: cur = cur.children[x] continue except KeyError: pass # optimistic: create the node first then look if it was correct to do so cur = self.__class__(x, cur) try: os.stat(cur.abspath()) except OSError: cur.evict() return None ret = cur try: os.stat(ret.abspath()) except OSError: ret.evict() return None try: while not getattr(cur.parent, 'cache_isdir', None): cur = cur.parent cur.cache_isdir = True except AttributeError: pass return ret def make_node(self, lst): """ Find or create a node without looking on the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur continue if getattr(cur, 'children', {}): if x in cur.children: cur = cur.children[x] continue else: cur.children = {} cur = self.__class__(x, cur) return cur def search_node(self, lst): """ Search for a node without looking on the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur else: try: cur = cur.children[x] except (AttributeError, KeyError): return None return cur def path_from(self, node): """ Path of this node seen from the other:: def build(bld): n1 = bld.path.find_node('foo/bar/xyz.txt') n2 = bld.path.find_node('foo/stuff/') n1.path_from(n2) # '../bar/xyz.txt' :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` """ c1 = self c2 = node c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while id(c1) != id(c2): lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent for i in range(up): lst.append('..') lst.reverse() return os.sep.join(lst) or '.' def abspath(self): """ Absolute path. A cache is kept in the context as ``cache_node_abspath`` """ try: return self.cache_abspath except AttributeError: pass # think twice before touching this (performance + complexity + correctness) if os.sep == '/': if not self.parent: val = os.sep elif not self.parent.name: val = os.sep + self.name else: val = self.parent.abspath() + os.sep + self.name else: if not self.parent: val = '' elif not self.parent.name: val = self.name + os.sep else: val = self.parent.abspath().rstrip(os.sep) + os.sep + self.name self.cache_abspath = val return val def is_child_of(self, node): """ Does this node belong to the subtree node?:: def build(bld): node = bld.path.find_node('wscript') node.is_child_of(bld.path) # True :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` """ p = self diff = self.height() - node.height() while diff > 0: diff -= 1 p = p.parent return id(p) == id(node) def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True): """ Semi-private and recursive method used by ant_glob. :param accept: function used for accepting/rejecting a node, returns the patterns that can be still accepted in recursion :type accept: function :param maxdepth: maximum depth in the filesystem (25) :type maxdepth: int :param pats: list of patterns to accept and list of patterns to exclude :type pats: tuple :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool """ dircont = self.listdir() dircont.sort() try: lst = set(self.children.keys()) except AttributeError: self.children = {} else: if remove: for x in lst - set(dircont): self.children[x].evict() for name in dircont: npats = accept(name, pats) if npats and npats[0]: accepted = [] in npats[0] node = self.make_node([name]) isdir = os.path.isdir(node.abspath()) if accepted: if isdir: if dir: yield node else: if src: yield node if getattr(node, 'cache_isdir', None) or isdir: node.cache_isdir = True if maxdepth: for k in node.ant_iter(accept=accept, maxdepth=maxdepth - 1, pats=npats, dir=dir, src=src, remove=remove): yield k raise StopIteration def ant_glob(self, *k, **kw): """ This method is used for finding files across folders. It behaves like ant patterns: * ``**/*`` find all files recursively * ``**/*.class`` find all files ending by .class * ``..`` find files having two dot characters For example:: def configure(cfg): cfg.path.ant_glob('**/*.cpp') # find all .cpp files cfg.root.ant_glob('etc/*.txt') # using the filesystem root can be slow cfg.path.ant_glob('*.cpp', excl=['*.c'], src=True, dir=False) For more information see http://ant.apache.org/manual/dirtasks.html The nodes that correspond to files and folders that do not exist will be removed. To prevent this behaviour, pass 'remove=False' :param incl: ant patterns or list of patterns to include :type incl: string or list of strings :param excl: ant patterns or list of patterns to exclude :type excl: string or list of strings :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool :param maxdepth: maximum depth of recursion :type maxdepth: int :param ignorecase: ignore case while matching (False by default) :type ignorecase: bool """ src = kw.get('src', True) dir = kw.get('dir', False) excl = kw.get('excl', exclude_regs) incl = k and k[0] or kw.get('incl', '**') reflags = kw.get('ignorecase', 0) and re.I def to_pat(s): lst = Utils.to_list(s) ret = [] for x in lst: x = x.replace('\\', '/').replace('//', '/') if x.endswith('/'): x += '**' lst2 = x.split('/') accu = [] for k in lst2: if k == '**': accu.append(k) else: k = k.replace('.', '[.]').replace('*','.*').replace('?', '.').replace('+', '\\+') k = '^%s$' % k try: #print "pattern", k accu.append(re.compile(k, flags=reflags)) except Exception as e: raise Errors.WafError("Invalid pattern: %s" % k, e) ret.append(accu) return ret def filtre(name, nn): ret = [] for lst in nn: if not lst: pass elif lst[0] == '**': ret.append(lst) if len(lst) > 1: if lst[1].match(name): ret.append(lst[2:]) else: ret.append([]) elif lst[0].match(name): ret.append(lst[1:]) return ret def accept(name, pats): nacc = filtre(name, pats[0]) nrej = filtre(name, pats[1]) if [] in nrej: nacc = [] return [nacc, nrej] ret = [x for x in self.ant_iter(accept=accept, pats=[to_pat(incl), to_pat(excl)], maxdepth=25, dir=dir, src=src, remove=kw.get('remove', True))] if kw.get('flat', False): return ' '.join([x.path_from(self) for x in ret]) return ret # -------------------------------------------------------------------------------- # the following methods require the source/build folders (bld.srcnode/bld.bldnode) # using a subclass is a possibility, but is that really necessary? # -------------------------------------------------------------------------------- def is_src(self): """ True if the node is below the source directory note: !is_src does not imply is_bld() :rtype: bool """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) while cur.parent: if id(cur) == y: return False if id(cur) == x: return True cur = cur.parent return False def is_bld(self): """ True if the node is below the build directory note: !is_bld does not imply is_src :rtype: bool """ cur = self y = id(self.ctx.bldnode) while cur.parent: if id(cur) == y: return True cur = cur.parent return False def get_src(self): """ Return the equivalent src node (or self if not possible) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) lst = [] while cur.parent: if id(cur) == y: lst.reverse() return self.ctx.srcnode.make_node(lst) if id(cur) == x: return self lst.append(cur.name) cur = cur.parent return self def get_bld(self): """ Return the equivalent bld node (or self if not possible) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) lst = [] while cur.parent: if id(cur) == y: return self if id(cur) == x: lst.reverse() return self.ctx.bldnode.make_node(lst) lst.append(cur.name) cur = cur.parent # the file is external to the current project, make a fake root in the current build directory lst.reverse() if lst and Utils.is_win32 and len(lst[0]) == 2 and lst[0].endswith(':'): lst[0] = lst[0][0] return self.ctx.bldnode.make_node(['__root__'] + lst) def find_resource(self, lst): """ Try to find a declared build node or a source file :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.get_bld().search_node(lst) if not node: self = self.get_src() node = self.find_node(lst) if node: if os.path.isdir(node.abspath()): return None return node def find_or_declare(self, lst): """ if 'self' is in build directory, try to return an existing node if no node is found, go to the source directory try to find an existing node in the source directory if no node is found, create it in the build directory :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.get_bld().search_node(lst) if node: if not os.path.isfile(node.abspath()): node.sig = None node.parent.mkdir() return node self = self.get_src() node = self.find_node(lst) if node: if not os.path.isfile(node.abspath()): node.sig = None node.parent.mkdir() return node node = self.get_bld().make_node(lst) node.parent.mkdir() return node def find_dir(self, lst): """ Search for a folder in the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.find_node(lst) try: if not os.path.isdir(node.abspath()): return None except (OSError, AttributeError): # the node might be None, and raise an AttributeError return None return node # helpers for building things def change_ext(self, ext, ext_in=None): """ :return: A build node of the same path, but with a different extension :rtype: :py:class:`waflib.Node.Node` """ name = self.name if ext_in is None: k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext else: name = name[:- len(ext_in)] + ext return self.parent.find_or_declare([name]) def nice_path(self, env=None): """ Return the path seen from the launch directory. Can be used for opening files easily (copy-paste in the console). """ return self.path_from(self.ctx.launch_node()) def bldpath(self): "Path seen from the build directory default/src/foo.cpp" return self.path_from(self.ctx.bldnode) def srcpath(self): "Path seen from the source directory ../src/foo.cpp" return self.path_from(self.ctx.srcnode) def relpath(self): "If a file in the build directory, bldpath, else srcpath" cur = self x = id(self.ctx.bldnode) while cur.parent: if id(cur) == x: return self.bldpath() cur = cur.parent return self.srcpath() def bld_dir(self): "Build path without the file name" return self.parent.bldpath() def bld_base(self): "Build path without the extension: src/dir/foo(.cpp)" s = os.path.splitext(self.name)[0] return self.bld_dir() + os.sep + s def get_bld_sig(self): """ Node signature, assuming the file is in the build directory """ try: return self.cache_sig except AttributeError: pass if not self.is_bld() or self.ctx.bldnode is self.ctx.srcnode: self.sig = Utils.h_file(self.abspath()) self.cache_sig = ret = self.sig return ret # TODO Waf 1.8 search = search_node pickle_lock = Utils.threading.Lock() """Lock mandatory for thread-safe node serialization""" class Nod3(Node): """Mandatory subclass for thread-safe node serialization""" pass # do not remove debian/waf-1.7/waflib/Scripting.py0000664000000000000000000003544712145745420014051 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "Module called for configuring, compiling and installing targets" import os, shlex, shutil, traceback, errno, sys, stat from waflib import Utils, Configure, Logs, Options, ConfigSet, Context, Errors, Build, Node build_dir_override = None no_climb_commands = ['configure'] default_cmd = "build" def waf_entry_point(current_directory, version, wafdir): """ This is the main entry point, all Waf execution starts here. :param current_directory: absolute path representing the current directory :type current_directory: string :param version: version number :type version: string :param wafdir: absolute path representing the directory of the waf library :type wafdir: string """ Logs.init_log() if Context.WAFVERSION != version: Logs.error('Waf script %r and library %r do not match (directory %r)' % (version, Context.WAFVERSION, wafdir)) sys.exit(1) if '--version' in sys.argv: Context.run_dir = current_directory ctx = Context.create_context('options') ctx.curdir = current_directory ctx.parse_args() sys.exit(0) Context.waf_dir = wafdir Context.launch_dir = current_directory # if 'configure' is in the commands, do not search any further no_climb = os.environ.get('NOCLIMB', None) if not no_climb: for k in no_climb_commands: if k in sys.argv: no_climb = True break # try to find a lock file (if the project was configured) # at the same time, store the first wscript file seen cur = current_directory while cur: lst = os.listdir(cur) if Options.lockfile in lst: env = ConfigSet.ConfigSet() try: env.load(os.path.join(cur, Options.lockfile)) ino = os.stat(cur)[stat.ST_INO] except Exception: pass else: # check if the folder was not moved for x in [env.run_dir, env.top_dir, env.out_dir]: if Utils.is_win32: if cur == x: load = True break else: # if the filesystem features symlinks, compare the inode numbers try: ino2 = os.stat(x)[stat.ST_INO] except OSError: pass else: if ino == ino2: load = True break else: Logs.warn('invalid lock file in %s' % cur) load = False if load: Context.run_dir = env.run_dir Context.top_dir = env.top_dir Context.out_dir = env.out_dir break if not Context.run_dir: if Context.WSCRIPT_FILE in lst: Context.run_dir = cur next = os.path.dirname(cur) if next == cur: break cur = next if no_climb: break if not Context.run_dir: if '-h' in sys.argv or '--help' in sys.argv: Logs.warn('No wscript file found: the help message may be incomplete') Context.run_dir = current_directory ctx = Context.create_context('options') ctx.curdir = current_directory ctx.parse_args() sys.exit(0) Logs.error('Waf: Run from a directory containing a file named %r' % Context.WSCRIPT_FILE) sys.exit(1) try: os.chdir(Context.run_dir) except OSError: Logs.error('Waf: The folder %r is unreadable' % Context.run_dir) sys.exit(1) try: set_main_module(Context.run_dir + os.sep + Context.WSCRIPT_FILE) except Errors.WafError as e: Logs.pprint('RED', e.verbose_msg) Logs.error(str(e)) sys.exit(1) except Exception as e: Logs.error('Waf: The wscript in %r is unreadable' % Context.run_dir, e) traceback.print_exc(file=sys.stdout) sys.exit(2) """ import cProfile, pstats cProfile.runctx("from waflib import Scripting; Scripting.run_commands()", {}, {}, 'profi.txt') p = pstats.Stats('profi.txt') p.sort_stats('time').print_stats(25) # or 'cumulative' """ try: run_commands() except Errors.WafError as e: if Logs.verbose > 1: Logs.pprint('RED', e.verbose_msg) Logs.error(e.msg) sys.exit(1) except SystemExit: raise except Exception as e: traceback.print_exc(file=sys.stdout) sys.exit(2) except KeyboardInterrupt: Logs.pprint('RED', 'Interrupted') sys.exit(68) #""" def set_main_module(file_path): """ Read the main wscript file into :py:const:`waflib.Context.Context.g_module` and bind default functions such as ``init``, ``dist``, ``distclean`` if not defined. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. :param file_path: absolute path representing the top-level wscript file :type file_path: string """ Context.g_module = Context.load_module(file_path) Context.g_module.root_path = file_path # note: to register the module globally, use the following: # sys.modules['wscript_main'] = g_module def set_def(obj): name = obj.__name__ if not name in Context.g_module.__dict__: setattr(Context.g_module, name, obj) for k in [update, dist, distclean, distcheck, update]: set_def(k) # add dummy init and shutdown functions if they're not defined if not 'init' in Context.g_module.__dict__: Context.g_module.init = Utils.nada if not 'shutdown' in Context.g_module.__dict__: Context.g_module.shutdown = Utils.nada if not 'options' in Context.g_module.__dict__: Context.g_module.options = Utils.nada def parse_options(): """ Parse the command-line options and initialize the logging system. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. """ Context.create_context('options').execute() if not Options.commands: Options.commands = [default_cmd] Options.commands = [x for x in Options.commands if x != 'options'] # issue 1076 # process some internal Waf options Logs.verbose = Options.options.verbose Logs.init_log() if Options.options.zones: Logs.zones = Options.options.zones.split(',') if not Logs.verbose: Logs.verbose = 1 elif Logs.verbose > 0: Logs.zones = ['runner'] if Logs.verbose > 2: Logs.zones = ['*'] def run_command(cmd_name): """ Execute a single command. Called by :py:func:`waflib.Scripting.run_commands`. :param cmd_name: command to execute, like ``build`` :type cmd_name: string """ ctx = Context.create_context(cmd_name) ctx.log_timer = Utils.Timer() ctx.options = Options.options # provided for convenience ctx.cmd = cmd_name ctx.execute() return ctx def run_commands(): """ Execute the commands that were given on the command-line, and the other options Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed after :py:func:`waflib.Scripting.parse_options`. """ parse_options() run_command('init') while Options.commands: cmd_name = Options.commands.pop(0) ctx = run_command(cmd_name) Logs.info('%r finished successfully (%s)' % (cmd_name, str(ctx.log_timer))) run_command('shutdown') ########################################################################################### def _can_distclean(name): # WARNING: this method may disappear anytime for k in '.o .moc .exe'.split(): if name.endswith(k): return True return False def distclean_dir(dirname): """ Distclean function called in the particular case when:: top == out :param dirname: absolute path of the folder to clean :type dirname: string """ for (root, dirs, files) in os.walk(dirname): for f in files: if _can_distclean(f): fname = root + os.sep + f try: os.unlink(fname) except OSError: Logs.warn('Could not remove %r' % fname) for x in [Context.DBFILE, 'config.log']: try: os.unlink(x) except OSError: pass try: shutil.rmtree('c4che') except OSError: pass def distclean(ctx): '''removes the build directory''' lst = os.listdir('.') for f in lst: if f == Options.lockfile: try: proj = ConfigSet.ConfigSet(f) except IOError: Logs.warn('Could not read %r' % f) continue if proj['out_dir'] != proj['top_dir']: try: shutil.rmtree(proj['out_dir']) except IOError: pass except OSError as e: if e.errno != errno.ENOENT: Logs.warn('project %r cannot be removed' % proj[Context.OUT]) else: distclean_dir(proj['out_dir']) for k in (proj['out_dir'], proj['top_dir'], proj['run_dir']): try: os.remove(os.path.join(k, Options.lockfile)) except OSError as e: if e.errno != errno.ENOENT: Logs.warn('file %r cannot be removed' % f) # remove the local waf cache if f.startswith('.waf') and not Options.commands: shutil.rmtree(f, ignore_errors=True) class Dist(Context.Context): '''creates an archive containing the project source code''' cmd = 'dist' fun = 'dist' algo = 'tar.bz2' ext_algo = {} def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() def archive(self): """ Create the archive. """ import tarfile arch_name = self.get_arch_name() try: self.base_path except AttributeError: self.base_path = self.path node = self.base_path.make_node(arch_name) try: node.delete() except Exception: pass files = self.get_files() if self.algo.startswith('tar.'): tar = tarfile.open(arch_name, 'w:' + self.algo.replace('tar.', '')) for x in files: self.add_tar_file(x, tar) tar.close() elif self.algo == 'zip': import zipfile zip = zipfile.ZipFile(arch_name, 'w', compression=zipfile.ZIP_DEFLATED) for x in files: archive_name = self.get_base_name() + '/' + x.path_from(self.base_path) zip.write(x.abspath(), archive_name, zipfile.ZIP_DEFLATED) zip.close() else: self.fatal('Valid algo types are tar.bz2, tar.gz or zip') try: from hashlib import sha1 as sha except ImportError: from sha import sha try: digest = " (sha=%r)" % sha(node.read()).hexdigest() except Exception: digest = '' Logs.info('New archive created: %s%s' % (self.arch_name, digest)) def get_tar_path(self, node): """ return the path to use for a node in the tar archive, the purpose of this is to let subclases resolve symbolic links or to change file names """ return node.abspath() def add_tar_file(self, x, tar): """ Add a file to the tar archive. Transform symlinks into files if the files lie out of the project tree. """ p = self.get_tar_path(x) tinfo = tar.gettarinfo(name=p, arcname=self.get_tar_prefix() + '/' + x.path_from(self.base_path)) tinfo.uid = 0 tinfo.gid = 0 tinfo.uname = 'root' tinfo.gname = 'root' fu = None try: fu = open(p, 'rb') tar.addfile(tinfo, fileobj=fu) finally: if fu: fu.close() def get_tar_prefix(self): try: return self.tar_prefix except AttributeError: return self.get_base_name() def get_arch_name(self): """ Return the name of the archive to create. Change the default value by setting *arch_name*:: def dist(ctx): ctx.arch_name = 'ctx.tar.bz2' :rtype: string """ try: self.arch_name except AttributeError: self.arch_name = self.get_base_name() + '.' + self.ext_algo.get(self.algo, self.algo) return self.arch_name def get_base_name(self): """ Return the default name of the main directory in the archive, which is set to *appname-version*. Set the attribute *base_name* to change the default value:: def dist(ctx): ctx.base_name = 'files' :rtype: string """ try: self.base_name except AttributeError: appname = getattr(Context.g_module, Context.APPNAME, 'noname') version = getattr(Context.g_module, Context.VERSION, '1.0') self.base_name = appname + '-' + version return self.base_name def get_excl(self): """ Return the patterns to exclude for finding the files in the top-level directory. Set the attribute *excl* to change the default value:: def dist(ctx): ctx.excl = 'build **/*.o **/*.class' :rtype: string """ try: return self.excl except AttributeError: self.excl = Node.exclude_regs + ' **/waf-1.7.* **/.waf-1.7* **/waf3-1.7.* **/.waf3-1.7* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' nd = self.root.find_node(Context.out_dir) if nd: self.excl += ' ' + nd.path_from(self.base_path) return self.excl def get_files(self): """ The files to package are searched automatically by :py:func:`waflib.Node.Node.ant_glob`. Set *files* to prevent this behaviour:: def dist(ctx): ctx.files = ctx.path.find_node('wscript') The files are searched from the directory 'base_path', to change it, set:: def dist(ctx): ctx.base_path = path :rtype: list of :py:class:`waflib.Node.Node` """ try: files = self.files except AttributeError: files = self.base_path.ant_glob('**/*', excl=self.get_excl()) return files def dist(ctx): '''makes a tarball for redistributing the sources''' pass class DistCheck(Dist): """ Create an archive of the project, and try to build the project in a temporary directory:: $ waf distcheck """ fun = 'distcheck' cmd = 'distcheck' def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() self.check() def check(self): """ Create the archive, uncompress it and try to build the project """ import tempfile, tarfile t = None try: t = tarfile.open(self.get_arch_name()) for x in t: t.extract(x) finally: if t: t.close() cfg = [] if Options.options.distcheck_args: cfg = shlex.split(Options.options.distcheck_args) else: cfg = [x for x in sys.argv if x.startswith('-')] instdir = tempfile.mkdtemp('.inst', self.get_base_name()) ret = Utils.subprocess.Popen([sys.argv[0], 'configure', 'install', 'uninstall', '--destdir=' + instdir] + cfg, cwd=self.get_base_name()).wait() if ret: raise Errors.WafError('distcheck failed with code %i' % ret) if os.path.exists(instdir): raise Errors.WafError('distcheck succeeded, but files were left in %s' % instdir) shutil.rmtree(self.get_base_name()) def distcheck(ctx): '''checks if the project compiles (tarball from 'dist')''' pass def update(ctx): '''updates the plugins from the *waflib/extras* directory''' lst = Options.options.files.split(',') if not lst: lst = [x for x in Utils.listdir(Context.waf_dir + '/waflib/extras') if x.endswith('.py')] for x in lst: tool = x.replace('.py', '') try: Configure.download_tool(tool, force=True, ctx=ctx) except Errors.WafError: Logs.error('Could not find the tool %s in the remote repository' % x) def autoconfigure(execute_method): """ Decorator used to set the commands that can be configured automatically """ def execute(self): if not Configure.autoconfig: return execute_method(self) env = ConfigSet.ConfigSet() do_config = False try: env.load(os.path.join(Context.top_dir, Options.lockfile)) except Exception: Logs.warn('Configuring the project') do_config = True else: if env.run_dir != Context.run_dir: do_config = True else: h = 0 for f in env['files']: h = hash((h, Utils.readf(f, 'rb'))) do_config = h != env.hash if do_config: Options.commands.insert(0, self.cmd) Options.commands.insert(0, 'configure') return return execute_method(self) return execute Build.BuildContext.execute = autoconfigure(Build.BuildContext.execute) debian/waf-1.7/waflib/TaskGen.py0000664000000000000000000005560612145745420013442 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Task generators The class :py:class:`waflib.TaskGen.task_gen` encapsulates the creation of task objects (low-level code) The instances can have various parameters, but the creation of task nodes (Task.py) is always postponed. To achieve this, various methods are called from the method "apply" """ import copy, re, os from waflib import Task, Utils, Logs, Errors, ConfigSet, Node feats = Utils.defaultdict(set) """remember the methods declaring features""" class task_gen(object): """ Instances of this class create :py:class:`waflib.Task.TaskBase` when calling the method :py:meth:`waflib.TaskGen.task_gen.post` from the main thread. A few notes: * The methods to call (*self.meths*) can be specified dynamically (removing, adding, ..) * The 'features' are used to add methods to self.meths and then execute them * The attribute 'path' is a node representing the location of the task generator * The tasks created are added to the attribute *tasks* * The attribute 'idx' is a counter of task generators in the same path """ mappings = {} prec = Utils.defaultdict(list) def __init__(self, *k, **kw): """ The task generator objects predefine various attributes (source, target) for possible processing by process_rule (make-like rules) or process_source (extensions, misc methods) The tasks are stored on the attribute 'tasks'. They are created by calling methods listed in self.meths *or* referenced in the attribute features A topological sort is performed to ease the method re-use. The extra key/value elements passed in kw are set as attributes """ # so we will have to play with directed acyclic graphs # detect cycles, etc self.source = '' self.target = '' self.meths = [] """ List of method names to execute (it is usually a good idea to avoid touching this) """ self.prec = Utils.defaultdict(list) """ Precedence table for sorting the methods in self.meths """ self.mappings = {} """ List of mappings {extension -> function} for processing files by extension """ self.features = [] """ List of feature names for bringing new methods in """ self.tasks = [] """ List of tasks created. """ if not 'bld' in kw: # task generators without a build context :-/ self.env = ConfigSet.ConfigSet() self.idx = 0 self.path = None else: self.bld = kw['bld'] self.env = self.bld.env.derive() self.path = self.bld.path # emulate chdir when reading scripts # provide a unique id try: self.idx = self.bld.idx[id(self.path)] = self.bld.idx.get(id(self.path), 0) + 1 except AttributeError: self.bld.idx = {} self.idx = self.bld.idx[id(self.path)] = 1 for key, val in kw.items(): setattr(self, key, val) def __str__(self): """for debugging purposes""" return "" % (self.name, self.path.abspath()) def __repr__(self): """for debugging purposes""" lst = [] for x in self.__dict__.keys(): if x not in ['env', 'bld', 'compiled_tasks', 'tasks']: lst.append("%s=%s" % (x, repr(getattr(self, x)))) return "bld(%s) in %s" % (", ".join(lst), self.path.abspath()) def get_name(self): """ If not set, the name is computed from the target name:: def build(bld): x = bld(name='foo') x.get_name() # foo y = bld(target='bar') y.get_name() # bar :rtype: string :return: name of this task generator """ try: return self._name except AttributeError: if isinstance(self.target, list): lst = [str(x) for x in self.target] name = self._name = ','.join(lst) else: name = self._name = str(self.target) return name def set_name(self, name): self._name = name name = property(get_name, set_name) def to_list(self, val): """ Ensure that a parameter is a list :type val: string or list of string :param val: input to return as a list :rtype: list """ if isinstance(val, str): return val.split() else: return val def post(self): """ Create task objects. The following operations are performed: #. The body of this method is called only once and sets the attribute ``posted`` #. The attribute ``features`` is used to add more methods in ``self.meths`` #. The methods are sorted by the precedence table ``self.prec`` or `:waflib:attr:waflib.TaskGen.task_gen.prec` #. The methods are then executed in order #. The tasks created are added to :py:attr:`waflib.TaskGen.task_gen.tasks` """ # we could add a decorator to let the task run once, but then python 2.3 will be difficult to support if getattr(self, 'posted', None): #error("OBJECT ALREADY POSTED" + str( self)) return False self.posted = True keys = set(self.meths) # add the methods listed in the features self.features = Utils.to_list(self.features) for x in self.features + ['*']: st = feats[x] if not st: if not x in Task.classes: Logs.warn('feature %r does not exist - bind at least one method to it' % x) keys.update(list(st)) # ironpython 2.7 wants the cast to list # copy the precedence table prec = {} prec_tbl = self.prec or task_gen.prec for x in prec_tbl: if x in keys: prec[x] = prec_tbl[x] # elements disconnected tmp = [] for a in keys: for x in prec.values(): if a in x: break else: tmp.append(a) tmp.sort() # topological sort out = [] while tmp: e = tmp.pop() if e in keys: out.append(e) try: nlst = prec[e] except KeyError: pass else: del prec[e] for x in nlst: for y in prec: if x in prec[y]: break else: tmp.append(x) if prec: raise Errors.WafError('Cycle detected in the method execution %r' % prec) out.reverse() self.meths = out # then we run the methods in order Logs.debug('task_gen: posting %s %d' % (self, id(self))) for x in out: try: v = getattr(self, x) except AttributeError: raise Errors.WafError('%r is not a valid task generator method' % x) Logs.debug('task_gen: -> %s (%d)' % (x, id(self))) v() Logs.debug('task_gen: posted %s' % self.name) return True def get_hook(self, node): """ :param node: Input file to process :type node: :py:class:`waflib.Tools.Node.Node` :return: A method able to process the input node by looking at the extension :rtype: function """ name = node.name for k in self.mappings: if name.endswith(k): return self.mappings[k] for k in task_gen.mappings: if name.endswith(k): return task_gen.mappings[k] raise Errors.WafError("File %r has no mapping in %r (did you forget to load a waf tool?)" % (node, task_gen.mappings.keys())) def create_task(self, name, src=None, tgt=None): """ Wrapper for creating task instances. The classes are retrieved from the context class if possible, then from the global dict Task.classes. :param name: task class name :type name: string :param src: input nodes :type src: list of :py:class:`waflib.Tools.Node.Node` :param tgt: output nodes :type tgt: list of :py:class:`waflib.Tools.Node.Node` :return: A task object :rtype: :py:class:`waflib.Task.TaskBase` """ task = Task.classes[name](env=self.env.derive(), generator=self) if src: task.set_inputs(src) if tgt: task.set_outputs(tgt) self.tasks.append(task) return task def clone(self, env): """ Make a copy of a task generator. Once the copy is made, it is necessary to ensure that the it does not create the same output files as the original, or the same files may be compiled several times. :param env: A configuration set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :return: A copy :rtype: :py:class:`waflib.TaskGen.task_gen` """ newobj = self.bld() for x in self.__dict__: if x in ['env', 'bld']: continue elif x in ['path', 'features']: setattr(newobj, x, getattr(self, x)) else: setattr(newobj, x, copy.copy(getattr(self, x))) newobj.posted = False if isinstance(env, str): newobj.env = self.bld.all_envs[env].derive() else: newobj.env = env.derive() return newobj def declare_chain(name='', rule=None, reentrant=None, color='BLUE', ext_in=[], ext_out=[], before=[], after=[], decider=None, scan=None, install_path=None, shell=False): """ Create a new mapping and a task class for processing files by extension. See Tools/flex.py for an example. :param name: name for the task class :type name: string :param rule: function to execute or string to be compiled in a function :type rule: string or function :param reentrant: re-inject the output file in the process (done automatically, set to 0 to disable) :type reentrant: int :param color: color for the task output :type color: string :param ext_in: execute the task only after the files of such extensions are created :type ext_in: list of string :param ext_out: execute the task only before files of such extensions are processed :type ext_out: list of string :param before: execute instances of this task before classes of the given names :type before: list of string :param after: execute instances of this task after classes of the given names :type after: list of string :param decider: if present, use it to create the output nodes for the task :type decider: function :param scan: scanner function for the task :type scan: function :param install_path: installation path for the output nodes :type install_path: string """ ext_in = Utils.to_list(ext_in) ext_out = Utils.to_list(ext_out) if not name: name = rule cls = Task.task_factory(name, rule, color=color, ext_in=ext_in, ext_out=ext_out, before=before, after=after, scan=scan, shell=shell) def x_file(self, node): ext = decider and decider(self, node) or cls.ext_out if ext_in: _ext_in = ext_in[0] tsk = self.create_task(name, node) cnt = 0 keys = list(self.mappings.keys()) + list(self.__class__.mappings.keys()) for x in ext: k = node.change_ext(x, ext_in=_ext_in) tsk.outputs.append(k) if reentrant != None: if cnt < int(reentrant): self.source.append(k) else: for y in keys: # ~ nfile * nextensions :-/ if k.name.endswith(y): self.source.append(k) break cnt += 1 if install_path: self.bld.install_files(install_path, tsk.outputs) return tsk for x in cls.ext_in: task_gen.mappings[x] = x_file return x_file def taskgen_method(func): """ Decorator: register a method as a task generator method. The function must accept a task generator as first parameter:: from waflib.TaskGen import taskgen_method @taskgen_method def mymethod(self): pass :param func: task generator method to add :type func: function :rtype: function """ setattr(task_gen, func.__name__, func) return func def feature(*k): """ Decorator: register a task generator method that will be executed when the object attribute 'feature' contains the corresponding key(s):: from waflib.Task import feature @feature('myfeature') def myfunction(self): print('that is my feature!') def build(bld): bld(features='myfeature') :param k: feature names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for name in k: feats[name].update([func.__name__]) return func return deco def before_method(*k): """ Decorator: register a task generator method which will be executed before the functions of given name(s):: from waflib.TaskGen import feature, before @feature('myfeature') @before_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not func.__name__ in task_gen.prec[fun_name]: task_gen.prec[fun_name].append(func.__name__) #task_gen.prec[fun_name].sort() return func return deco before = before_method def after_method(*k): """ Decorator: register a task generator method which will be executed after the functions of given name(s):: from waflib.TaskGen import feature, after @feature('myfeature') @after_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not fun_name in task_gen.prec[func.__name__]: task_gen.prec[func.__name__].append(fun_name) #task_gen.prec[func.__name__].sort() return func return deco after = after_method def extension(*k): """ Decorator: register a task generator method which will be invoked during the processing of source files for the extension given:: from waflib import Task class mytask(Task): run_str = 'cp ${SRC} ${TGT}' @extension('.moo') def create_maa_file(self, node): self.create_task('mytask', node, node.change_ext('.maa')) def build(bld): bld(source='foo.moo') """ def deco(func): setattr(task_gen, func.__name__, func) for x in k: task_gen.mappings[x] = func return func return deco # --------------------------------------------------------------- # The following methods are task generator methods commonly used # they are almost examples, the rest of waf core does not depend on them @taskgen_method def to_nodes(self, lst, path=None): """ Convert the input list into a list of nodes. It is used by :py:func:`waflib.TaskGen.process_source` and :py:func:`waflib.TaskGen.process_rule`. It is designed for source files, for folders, see :py:func:`waflib.Tools.ccroot.to_incnodes`: :param lst: input list :type lst: list of string and nodes :param path: path from which to search the nodes (by default, :py:attr:`waflib.TaskGen.task_gen.path`) :type path: :py:class:`waflib.Tools.Node.Node` :rtype: list of :py:class:`waflib.Tools.Node.Node` """ tmp = [] path = path or self.path find = path.find_resource if isinstance(lst, self.path.__class__): lst = [lst] # either a list or a string, convert to a list of nodes for x in Utils.to_list(lst): if isinstance(x, str): node = find(x) else: node = x if not node: raise Errors.WafError("source not found: %r in %r" % (x, self)) tmp.append(node) return tmp @feature('*') def process_source(self): """ Process each element in the attribute ``source`` by extension. #. The *source* list is converted through :py:meth:`waflib.TaskGen.to_nodes` to a list of :py:class:`waflib.Node.Node` first. #. File extensions are mapped to methods having the signature: ``def meth(self, node)`` by :py:meth:`waflib.TaskGen.extension` #. The method is retrieved through :py:meth:`waflib.TaskGen.task_gen.get_hook` #. When called, the methods may modify self.source to append more source to process #. The mappings can map an extension or a filename (see the code below) """ self.source = self.to_nodes(getattr(self, 'source', [])) for node in self.source: self.get_hook(node)(self, node) @feature('*') @before_method('process_source') def process_rule(self): """ Process the attribute ``rule``. When present, :py:meth:`waflib.TaskGen.process_source` is disabled:: def build(bld): bld(rule='cp ${SRC} ${TGT}', source='wscript', target='bar.txt') """ if not getattr(self, 'rule', None): return # create the task class name = str(getattr(self, 'name', None) or self.target or getattr(self.rule, '__name__', self.rule)) # or we can put the class in a cache for performance reasons try: cache = self.bld.cache_rule_attr except AttributeError: cache = self.bld.cache_rule_attr = {} cls = None if getattr(self, 'cache_rule', 'True'): try: cls = cache[(name, self.rule)] except KeyError: pass if not cls: cls = Task.task_factory(name, self.rule, getattr(self, 'vars', []), shell=getattr(self, 'shell', True), color=getattr(self, 'color', 'BLUE'), scan = getattr(self, 'scan', None)) if getattr(self, 'scan', None): cls.scan = self.scan elif getattr(self, 'deps', None): def scan(self): nodes = [] for x in self.generator.to_list(getattr(self.generator, 'deps', None)): node = self.generator.path.find_resource(x) if not node: self.generator.bld.fatal('Could not find %r (was it declared?)' % x) nodes.append(node) return [nodes, []] cls.scan = scan if getattr(self, 'update_outputs', None): Task.update_outputs(cls) if getattr(self, 'always', None): Task.always_run(cls) for x in ['after', 'before', 'ext_in', 'ext_out']: setattr(cls, x, getattr(self, x, [])) if getattr(self, 'cache_rule', 'True'): cache[(name, self.rule)] = cls # now create one instance tsk = self.create_task(name) if getattr(self, 'target', None): if isinstance(self.target, str): self.target = self.target.split() if not isinstance(self.target, list): self.target = [self.target] for x in self.target: if isinstance(x, str): tsk.outputs.append(self.path.find_or_declare(x)) else: x.parent.mkdir() # if a node was given, create the required folders tsk.outputs.append(x) if getattr(self, 'install_path', None): # from waf 1.5 # although convenient, it does not 1. allow to name the target file and 2. symlinks # TODO remove in waf 1.7 self.bld.install_files(self.install_path, tsk.outputs) if getattr(self, 'source', None): tsk.inputs = self.to_nodes(self.source) # bypass the execution of process_source by setting the source to an empty list self.source = [] if getattr(self, 'cwd', None): tsk.cwd = self.cwd @feature('seq') def sequence_order(self): """ Add a strict sequential constraint between the tasks generated by task generators. It works because task generators are posted in order. It will not post objects which belong to other folders. Example:: bld(features='javac seq') bld(features='jar seq') To start a new sequence, set the attribute seq_start, for example:: obj = bld(features='seq') obj.seq_start = True Note that the method is executed in last position. This is more an example than a widely-used solution. """ if self.meths and self.meths[-1] != 'sequence_order': self.meths.append('sequence_order') return if getattr(self, 'seq_start', None): return # all the tasks previously declared must be run before these if getattr(self.bld, 'prev', None): self.bld.prev.post() for x in self.bld.prev.tasks: for y in self.tasks: y.set_run_after(x) self.bld.prev = self re_m4 = re.compile('@(\w+)@', re.M) class subst_pc(Task.Task): """ Create *.pc* files from *.pc.in*. The task is executed whenever an input variable used in the substitution changes. """ def run(self): "Substitutes variables in a .in file" if getattr(self.generator, 'is_copy', None): self.outputs[0].write(self.inputs[0].read('rb'), 'wb') if getattr(self.generator, 'chmod', None): os.chmod(self.outputs[0].abspath(), self.generator.chmod) return code = self.inputs[0].read(encoding=getattr(self.generator, 'encoding', 'ISO8859-1')) if getattr(self.generator, 'subst_fun', None): code = self.generator.subst_fun(self, code) if code: self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'ISO8859-1')) return # replace all % by %% to prevent errors by % signs code = code.replace('%', '%%') # extract the vars foo into lst and replace @foo@ by %(foo)s lst = [] def repl(match): g = match.group if g(1): lst.append(g(1)) return "%%(%s)s" % g(1) return '' code = re_m4.sub(repl, code) try: d = self.generator.dct except AttributeError: d = {} for x in lst: tmp = getattr(self.generator, x, '') or self.env.get_flat(x) or self.env.get_flat(x.upper()) d[x] = str(tmp) code = code % d self.outputs[0].write(code, encoding=getattr(self.generator, 'encoding', 'ISO8859-1')) self.generator.bld.raw_deps[self.uid()] = self.dep_vars = lst # make sure the signature is updated try: delattr(self, 'cache_sig') except AttributeError: pass if getattr(self.generator, 'chmod', None): os.chmod(self.outputs[0].abspath(), self.generator.chmod) def sig_vars(self): """ Compute a hash (signature) of the variables used in the substitution """ bld = self.generator.bld env = self.env upd = self.m.update if getattr(self.generator, 'subst_fun', None): upd(Utils.h_fun(self.generator.subst_fun).encode()) # raw_deps: persistent custom values returned by the scanner vars = self.generator.bld.raw_deps.get(self.uid(), []) # hash both env vars and task generator attributes act_sig = bld.hash_env_vars(env, vars) upd(act_sig) lst = [getattr(self.generator, x, '') for x in vars] upd(Utils.h_list(lst)) return self.m.digest() @extension('.pc.in') def add_pcfile(self, node): """ Process *.pc.in* files to *.pc*. Install the results to ``${PREFIX}/lib/pkgconfig/`` def build(bld): bld(source='foo.pc.in', install_path='${LIBDIR}/pkgconfig/') """ tsk = self.create_task('subst_pc', node, node.change_ext('.pc', '.pc.in')) self.bld.install_files(getattr(self, 'install_path', '${LIBDIR}/pkgconfig/'), tsk.outputs) class subst(subst_pc): pass @feature('subst') @before_method('process_source', 'process_rule') def process_subst(self): """ Define a transformation that substitutes the contents of *source* files to *target* files:: def build(bld): bld( features='subst', source='foo.c.in', target='foo.c', install_path='${LIBDIR}/pkgconfig', VAR = 'val' ) The input files are supposed to contain macros of the form *@VAR@*, where *VAR* is an argument of the task generator object. This method overrides the processing by :py:meth:`waflib.TaskGen.process_source`. """ src = Utils.to_list(getattr(self, 'source', [])) if isinstance(src, Node.Node): src = [src] tgt = Utils.to_list(getattr(self, 'target', [])) if isinstance(tgt, Node.Node): tgt = [tgt] if len(src) != len(tgt): raise Errors.WafError('invalid number of source/target for %r' % self) for x, y in zip(src, tgt): if not x or not y: raise Errors.WafError('null source or target for %r' % self) a, b = None, None if isinstance(x, str) and isinstance(y, str) and x == y: a = self.path.find_node(x) b = self.path.get_bld().make_node(y) if not os.path.isfile(b.abspath()): b.sig = None b.parent.mkdir() else: if isinstance(x, str): a = self.path.find_resource(x) elif isinstance(x, Node.Node): a = x if isinstance(y, str): b = self.path.find_or_declare(y) elif isinstance(y, Node.Node): b = y if not a: raise Errors.WafError('cound not find %r for %r' % (x, self)) has_constraints = False tsk = self.create_task('subst', a, b) for k in ('after', 'before', 'ext_in', 'ext_out'): val = getattr(self, k, None) if val: has_constraints = True setattr(tsk, k, val) # paranoid safety measure for the general case foo.in->foo.h with ambiguous dependencies if not has_constraints and b.name.endswith('.h'): tsk.before = [k for k in ('c', 'cxx') if k in Task.classes] inst_to = getattr(self, 'install_path', None) if inst_to: self.bld.install_files(inst_to, b, chmod=getattr(self, 'chmod', Utils.O644)) self.source = [] debian/waf-1.7/waflib/Configure.py0000664000000000000000000003744112145745420014024 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Configuration system A :py:class:`waflib.Configure.ConfigurationContext` instance is created when ``waf configure`` is called, it is used to: * create data dictionaries (ConfigSet instances) * store the list of modules to import * hold configuration routines such as ``find_program``, etc """ import os, shlex, sys, time from waflib import ConfigSet, Utils, Options, Logs, Context, Build, Errors try: from urllib import request except ImportError: from urllib import urlopen else: urlopen = request.urlopen BREAK = 'break' """In case of a configuration error, break""" CONTINUE = 'continue' """In case of a configuration error, continue""" WAF_CONFIG_LOG = 'config.log' """Name of the configuration log file""" autoconfig = False """Execute the configuration automatically""" conf_template = '''# project %(app)s configured on %(now)s by # waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) # using %(args)s #''' def download_check(node): """ Hook to check for the tools which are downloaded. Replace with your function if necessary. """ pass def download_tool(tool, force=False, ctx=None): """ Download a Waf tool from the remote repository defined in :py:const:`waflib.Context.remote_repo`:: $ waf configure --download """ for x in Utils.to_list(Context.remote_repo): for sub in Utils.to_list(Context.remote_locs): url = '/'.join((x, sub, tool + '.py')) try: web = urlopen(url) try: if web.getcode() != 200: continue except AttributeError: pass except Exception: # on python3 urlopen throws an exception # python 2.3 does not have getcode and throws an exception to fail continue else: tmp = ctx.root.make_node(os.sep.join((Context.waf_dir, 'waflib', 'extras', tool + '.py'))) tmp.write(web.read(), 'wb') Logs.warn('Downloaded %s from %s' % (tool, url)) download_check(tmp) try: module = Context.load_tool(tool) except Exception: Logs.warn('The tool %s from %s is unusable' % (tool, url)) try: tmp.delete() except Exception: pass continue return module raise Errors.WafError('Could not load the Waf tool') class ConfigurationContext(Context.Context): '''configures the project''' cmd = 'configure' error_handlers = [] """ Additional functions to handle configuration errors """ def __init__(self, **kw): super(ConfigurationContext, self).__init__(**kw) self.environ = dict(os.environ) self.all_envs = {} self.top_dir = None self.out_dir = None self.tools = [] # tools loaded in the configuration, and that will be loaded when building self.hash = 0 self.files = [] self.tool_cache = [] self.setenv('') def setenv(self, name, env=None): """ Set a new config set for conf.env. If a config set of that name already exists, recall it without modification. The name is the filename prefix to save to ``c4che/NAME_cache.py``, and it is also used as *variants* by the build commands. Though related to variants, whatever kind of data may be stored in the config set:: def configure(cfg): cfg.env.ONE = 1 cfg.setenv('foo') cfg.env.ONE = 2 def build(bld): 2 == bld.env_of_name('foo').ONE :param name: name of the configuration set :type name: string :param env: ConfigSet to copy, or an empty ConfigSet is created :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ if name not in self.all_envs or env: if not env: env = ConfigSet.ConfigSet() self.prepare_env(env) else: env = env.derive() self.all_envs[name] = env self.variant = name def get_env(self): """Getter for the env property""" return self.all_envs[self.variant] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def init_dirs(self): """ Initialize the project directory and the build directory """ top = self.top_dir if not top: top = Options.options.top if not top: top = getattr(Context.g_module, Context.TOP, None) if not top: top = self.path.abspath() top = os.path.abspath(top) self.srcnode = (os.path.isabs(top) and self.root or self.path).find_dir(top) assert(self.srcnode) out = self.out_dir if not out: out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf_%s_' % sys.platform, '').replace('.lock-waf', '') self.bldnode = (os.path.isabs(out) and self.root or self.path).make_node(out) self.bldnode.mkdir() if not os.path.isdir(self.bldnode.abspath()): conf.fatal('Could not create the build directory %s' % self.bldnode.abspath()) def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.init_dirs() self.cachedir = self.bldnode.make_node(Build.CACHE_DIR) self.cachedir.mkdir() path = os.path.join(self.bldnode.abspath(), WAF_CONFIG_LOG) self.logger = Logs.make_logger(path, 'cfg') app = getattr(Context.g_module, 'APPNAME', '') if app: ver = getattr(Context.g_module, 'VERSION', '') if ver: app = "%s (%s)" % (app, ver) now = time.ctime() pyver = sys.hexversion systype = sys.platform args = " ".join(sys.argv) wafver = Context.WAFVERSION abi = Context.ABI self.to_log(conf_template % vars()) self.msg('Setting top to', self.srcnode.abspath()) self.msg('Setting out to', self.bldnode.abspath()) if id(self.srcnode) == id(self.bldnode): Logs.warn('Setting top == out (remember to use "update_outputs")') elif id(self.path) != id(self.srcnode): if self.srcnode.is_child_of(self.path): Logs.warn('Are you certain that you do not want to set top="." ?') super(ConfigurationContext, self).execute() self.store() Context.top_dir = self.srcnode.abspath() Context.out_dir = self.bldnode.abspath() # this will write a configure lock so that subsequent builds will # consider the current path as the root directory (see prepare_impl). # to remove: use 'waf distclean' env = ConfigSet.ConfigSet() env['argv'] = sys.argv env['options'] = Options.options.__dict__ env.run_dir = Context.run_dir env.top_dir = Context.top_dir env.out_dir = Context.out_dir # conf.hash & conf.files hold wscript files paths and hash # (used only by Configure.autoconfig) env['hash'] = self.hash env['files'] = self.files env['environ'] = dict(self.environ) if not self.env.NO_LOCK_IN_RUN: env.store(Context.run_dir + os.sep + Options.lockfile) if not self.env.NO_LOCK_IN_TOP: env.store(Context.top_dir + os.sep + Options.lockfile) if not self.env.NO_LOCK_IN_OUT: env.store(Context.out_dir + os.sep + Options.lockfile) def prepare_env(self, env): """ Insert *PREFIX*, *BINDIR* and *LIBDIR* values into ``env`` :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param env: a ConfigSet, usually ``conf.env`` """ if not env.PREFIX: if Options.options.prefix or Utils.is_win32: env.PREFIX = os.path.abspath(os.path.expanduser(Options.options.prefix)) else: env.PREFIX = '' if not env.BINDIR: env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env) if not env.LIBDIR: env.LIBDIR = Utils.subst_vars('${PREFIX}/lib', env) def store(self): """Save the config results into the cache file""" n = self.cachedir.make_node('build.config.py') n.write('version = 0x%x\ntools = %r\n' % (Context.HEXVERSION, self.tools)) if not self.all_envs: self.fatal('nothing to store in the configuration context!') for key in self.all_envs: tmpenv = self.all_envs[key] tmpenv.store(os.path.join(self.cachedir.abspath(), key + Build.CACHE_SUFFIX)) def load(self, input, tooldir=None, funs=None, download=True): """ Load Waf tools, which will be imported whenever a build is started. :param input: waf tools to import :type input: list of string :param tooldir: paths for the imports :type tooldir: list of string :param funs: functions to execute from the waf tools :type funs: list of string :param download: whether to download the tool from the waf repository :type download: bool """ tools = Utils.to_list(input) if tooldir: tooldir = Utils.to_list(tooldir) for tool in tools: # avoid loading the same tool more than once with the same functions # used by composite projects mag = (tool, id(self.env), funs) if mag in self.tool_cache: self.to_log('(tool %s is already loaded, skipping)' % tool) continue self.tool_cache.append(mag) module = None try: module = Context.load_tool(tool, tooldir) except ImportError as e: if Options.options.download: module = download_tool(tool, ctx=self) if not module: self.fatal('Could not load the Waf tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e)) else: self.fatal('Could not load the Waf tool %r from %r (try the --download option?):\n%s' % (tool, sys.path, e)) except Exception as e: self.to_log('imp %r (%r & %r)' % (tool, tooldir, funs)) self.to_log(Utils.ex_stack()) raise if funs is not None: self.eval_rules(funs) else: func = getattr(module, 'configure', None) if func: if type(func) is type(Utils.readf): func(self) else: self.eval_rules(func) self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) def post_recurse(self, node): """ Records the path and a hash of the scripts visited, see :py:meth:`waflib.Context.Context.post_recurse` :param node: script :type node: :py:class:`waflib.Node.Node` """ super(ConfigurationContext, self).post_recurse(node) self.hash = hash((self.hash, node.read('rb'))) self.files.append(node.abspath()) def eval_rules(self, rules): """ Execute the configuration tests. The method :py:meth:`waflib.Configure.ConfigurationContext.err_handler` is used to process the eventual exceptions :param rules: list of configuration method names :type rules: list of string """ self.rules = Utils.to_list(rules) for x in self.rules: f = getattr(self, x) if not f: self.fatal("No such method '%s'." % x) try: f() except Exception as e: ret = self.err_handler(x, e) if ret == BREAK: break elif ret == CONTINUE: continue else: raise def err_handler(self, fun, error): """ Error handler for the configuration tests, the default is to let the exception raise :param fun: configuration test :type fun: method :param error: exception :type error: exception """ pass def conf(f): """ Decorator: attach new configuration functions to :py:class:`waflib.Build.BuildContext` and :py:class:`waflib.Configure.ConfigurationContext`. The methods bound will accept a parameter named 'mandatory' to disable the configuration errors:: def configure(conf): conf.find_program('abc', mandatory=False) :param f: method to bind :type f: function """ def fun(*k, **kw): mandatory = True if 'mandatory' in kw: mandatory = kw['mandatory'] del kw['mandatory'] try: return f(*k, **kw) except Errors.ConfigurationError: if mandatory: raise setattr(ConfigurationContext, f.__name__, fun) setattr(Build.BuildContext, f.__name__, fun) return f @conf def add_os_flags(self, var, dest=None): """ Import operating system environment values into ``conf.env`` dict:: def configure(conf): conf.add_os_flags('CFLAGS') :param var: variable to use :type var: string :param dest: destination variable, by default the same as var :type dest: string """ # do not use 'get' to make certain the variable is not defined try: self.env.append_value(dest or var, shlex.split(self.environ[var])) except KeyError: pass @conf def cmd_to_list(self, cmd): """ Detect if a command is written in pseudo shell like ``ccache g++`` and return a list. :param cmd: command :type cmd: a string or a list of string """ if isinstance(cmd, str) and cmd.find(' '): try: os.stat(cmd) except OSError: return shlex.split(cmd) else: return [cmd] return cmd @conf def check_waf_version(self, mini='1.6.99', maxi='1.8.0'): """ Raise a Configuration error if the Waf version does not strictly match the given bounds:: conf.check_waf_version(mini='1.7.0', maxi='1.8.0') :type mini: number, tuple or string :param mini: Minimum required version :type maxi: number, tuple or string :param maxi: Maximum allowed version """ self.start_msg('Checking for waf version in %s-%s' % (str(mini), str(maxi))) ver = Context.HEXVERSION if Utils.num2ver(mini) > ver: self.fatal('waf version should be at least %r (%r found)' % (Utils.num2ver(mini), ver)) if Utils.num2ver(maxi) < ver: self.fatal('waf version should be at most %r (%r found)' % (Utils.num2ver(maxi), ver)) self.end_msg('ok') @conf def find_file(self, filename, path_list=[]): """ Find a file in a list of paths :param filename: name of the file to search for :param path_list: list of directories to search :return: the first occurrence filename or '' if filename could not be found """ for n in Utils.to_list(filename): for d in Utils.to_list(path_list): p = os.path.join(d, n) if os.path.exists(p): return p self.fatal('Could not find %r' % filename) @conf def find_program(self, filename, **kw): """ Search for a program on the operating system When var is used, you may set os.environ[var] to help find a specific program version, for example:: $ VALAC=/usr/bin/valac_test waf configure :param path_list: paths to use for searching :type param_list: list of string :param var: store the result to conf.env[var], by default use filename.upper() :type var: string :param ext: list of extensions for the binary (do not add an extension for portability) :type ext: list of string """ exts = kw.get('exts', Utils.is_win32 and '.exe,.com,.bat,.cmd' or ',.sh,.pl,.py') environ = kw.get('environ', os.environ) ret = '' filename = Utils.to_list(filename) var = kw.get('var', '') if not var: var = filename[0].upper() if self.env[var]: ret = self.env[var] elif var in environ: ret = environ[var] path_list = kw.get('path_list', '') if not ret: if path_list: path_list = Utils.to_list(path_list) else: path_list = environ.get('PATH', '').split(os.pathsep) if not isinstance(filename, list): filename = [filename] for a in exts.split(','): if ret: break for b in filename: if ret: break for c in path_list: if ret: break x = os.path.expanduser(os.path.join(c, b + a)) if os.path.isfile(x): ret = x if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER, filename) if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE, filename) self.msg('Checking for program ' + ','.join(filename), ret or False) self.to_log('find program=%r paths=%r var=%r -> %r' % (filename, path_list, var, ret)) if not ret: self.fatal(kw.get('errmsg', '') or 'Could not find the program %s' % ','.join(filename)) if var: self.env[var] = ret return ret @conf def find_perl_program(self, filename, path_list=[], var=None, environ=None, exts=''): """ Search for a perl program on the operating system :param filename: file to search for :type filename: string :param path_list: list of paths to look into :type path_list: list of string :param var: store the results into *conf.env.var* :type var: string :param environ: operating system environment to pass to :py:func:`waflib.Configure.find_program` :type environ: dict :param exts: extensions given to :py:func:`waflib.Configure.find_program` :type exts: list """ try: app = self.find_program(filename, path_list=path_list, var=var, environ=environ, exts=exts) except Exception: self.find_program('perl', var='PERL') app = self.find_file(filename, os.environ['PATH'].split(os.pathsep)) if not app: raise if var: self.env[var] = Utils.to_list(self.env['PERL']) + [app] self.msg('Checking for %r' % filename, app) debian/waf-1.7/waflib/Runner.py0000664000000000000000000002075312145745420013352 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Runner.py: Task scheduling and execution """ import random, atexit try: from queue import Queue except ImportError: from Queue import Queue from waflib import Utils, Task, Errors, Logs GAP = 10 """ Wait for free tasks if there are at least ``GAP * njobs`` in queue """ class TaskConsumer(Utils.threading.Thread): """ Task consumers belong to a pool of workers They wait for tasks in the queue and then use ``task.process(...)`` """ def __init__(self): Utils.threading.Thread.__init__(self) self.ready = Queue() """ Obtain :py:class:`waflib.Task.TaskBase` instances from this queue. """ self.setDaemon(1) self.start() def run(self): """ Loop over the tasks to execute """ try: self.loop() except Exception: pass def loop(self): """ Obtain tasks from :py:attr:`waflib.Runner.TaskConsumer.ready` and call :py:meth:`waflib.Task.TaskBase.process`. If the object is a function, execute it. """ while 1: tsk = self.ready.get() if not isinstance(tsk, Task.TaskBase): tsk(self) else: tsk.process() pool = Queue() """ Pool of task consumer objects """ def get_pool(): """ Obtain a task consumer from :py:attr:`waflib.Runner.pool`. Do not forget to put it back by using :py:func:`waflib.Runner.put_pool` and reset properly (original waiting queue). :rtype: :py:class:`waflib.Runner.TaskConsumer` """ try: return pool.get(False) except Exception: return TaskConsumer() def put_pool(x): """ Return a task consumer to the thread pool :py:attr:`waflib.Runner.pool` :param x: task consumer object :type x: :py:class:`waflib.Runner.TaskConsumer` """ pool.put(x) def _free_resources(): global pool lst = [] while pool.qsize(): lst.append(pool.get()) for x in lst: x.ready.put(None) for x in lst: x.join() pool = None atexit.register(_free_resources) class Parallel(object): """ Schedule the tasks obtained from the build context for execution. """ def __init__(self, bld, j=2): """ The initialization requires a build context reference for computing the total number of jobs. """ self.numjobs = j """ Number of consumers in the pool """ self.bld = bld """ Instance of :py:class:`waflib.Build.BuildContext` """ self.outstanding = [] """List of :py:class:`waflib.Task.TaskBase` that may be ready to be executed""" self.frozen = [] """List of :py:class:`waflib.Task.TaskBase` that cannot be executed immediately""" self.out = Queue(0) """List of :py:class:`waflib.Task.TaskBase` returned by the task consumers""" self.count = 0 """Amount of tasks that may be processed by :py:class:`waflib.Runner.TaskConsumer`""" self.processed = 1 """Amount of tasks processed""" self.stop = False """Error flag to stop the build""" self.error = [] """Tasks that could not be executed""" self.biter = None """Task iterator which must give groups of parallelizable tasks when calling ``next()``""" self.dirty = False """Flag to indicate that tasks have been executed, and that the build cache must be saved (call :py:meth:`waflib.Build.BuildContext.store`)""" def get_next_task(self): """ Obtain the next task to execute. :rtype: :py:class:`waflib.Task.TaskBase` """ if not self.outstanding: return None return self.outstanding.pop(0) def postpone(self, tsk): """ A task cannot be executed at this point, put it in the list :py:attr:`waflib.Runner.Parallel.frozen`. :param tsk: task :type tsk: :py:class:`waflib.Task.TaskBase` """ if random.randint(0, 1): self.frozen.insert(0, tsk) else: self.frozen.append(tsk) def refill_task_list(self): """ Put the next group of tasks to execute in :py:attr:`waflib.Runner.Parallel.outstanding`. """ while self.count > self.numjobs * GAP: self.get_out() while not self.outstanding: if self.count: self.get_out() elif self.frozen: try: cond = self.deadlock == self.processed except AttributeError: pass else: if cond: msg = 'check the build order for the tasks' for tsk in self.frozen: if not tsk.run_after: msg = 'check the methods runnable_status' break lst = [] for tsk in self.frozen: lst.append('%s\t-> %r' % (repr(tsk), [id(x) for x in tsk.run_after])) raise Errors.WafError('Deadlock detected: %s%s' % (msg, ''.join(lst))) self.deadlock = self.processed if self.frozen: self.outstanding += self.frozen self.frozen = [] elif not self.count: self.outstanding.extend(next(self.biter)) self.total = self.bld.total() break def add_more_tasks(self, tsk): """ Tasks may be added dynamically during the build by binding them to the task :py:attr:`waflib.Task.TaskBase.more_tasks` :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ if getattr(tsk, 'more_tasks', None): self.outstanding += tsk.more_tasks self.total += len(tsk.more_tasks) def get_out(self): """ Obtain one task returned from the task consumers, and update the task count. Add more tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`. :rtype: :py:attr:`waflib.Task.TaskBase` """ tsk = self.out.get() if not self.stop: self.add_more_tasks(tsk) self.count -= 1 self.dirty = True return tsk def error_handler(self, tsk): """ Called when a task cannot be executed. The flag :py:attr:`waflib.Runner.Parallel.stop` is set, unless the build is executed with:: $ waf build -k :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ if not self.bld.keep: self.stop = True self.error.append(tsk) def add_task(self, tsk): """ Pass a task to a consumer. :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ try: self.pool except AttributeError: self.init_task_pool() self.ready.put(tsk) def init_task_pool(self): # lazy creation, and set a common pool for all task consumers pool = self.pool = [get_pool() for i in range(self.numjobs)] self.ready = Queue(0) def setq(consumer): consumer.ready = self.ready for x in pool: x.ready.put(setq) return pool def free_task_pool(self): # return the consumers, setting a different queue for each of them def setq(consumer): consumer.ready = Queue(0) self.out.put(self) try: pool = self.pool except AttributeError: pass else: for x in pool: self.ready.put(setq) for x in pool: self.get_out() for x in pool: put_pool(x) self.pool = [] def start(self): """ Give tasks to :py:class:`waflib.Runner.TaskConsumer` instances until the build finishes or the ``stop`` flag is set. If only one job is used, then execute the tasks one by one, without consumers. """ self.total = self.bld.total() while not self.stop: self.refill_task_list() # consider the next task tsk = self.get_next_task() if not tsk: if self.count: # tasks may add new ones after they are run continue else: # no tasks to run, no tasks running, time to exit break if tsk.hasrun: # if the task is marked as "run", just skip it self.processed += 1 continue if self.stop: # stop immediately after a failure was detected break try: st = tsk.runnable_status() except Exception: self.processed += 1 # TODO waf 1.7 this piece of code should go in the error_handler tsk.err_msg = Utils.ex_stack() if not self.stop and self.bld.keep: tsk.hasrun = Task.SKIPPED if self.bld.keep == 1: # if -k stop at the first exception, if -kk try to go as far as possible if Logs.verbose > 1 or not self.error: self.error.append(tsk) self.stop = True else: if Logs.verbose > 1: self.error.append(tsk) continue tsk.hasrun = Task.EXCEPTION self.error_handler(tsk) continue if st == Task.ASK_LATER: self.postpone(tsk) elif st == Task.SKIP_ME: self.processed += 1 tsk.hasrun = Task.SKIPPED self.add_more_tasks(tsk) else: # run me: put the task in ready queue tsk.position = (self.processed, self.total) self.count += 1 tsk.master = self self.processed += 1 if self.numjobs == 1: tsk.process() else: self.add_task(tsk) # self.count represents the tasks that have been made available to the consumer threads # collect all the tasks after an error else the message may be incomplete while self.error and self.count: self.get_out() #print loop assert (self.count == 0 or self.stop) # free the task pool, if any self.free_task_pool() debian/waf-1.7/waflib/Tools/0000775000000000000000000000000012253225221012610 5ustar debian/waf-1.7/waflib/Tools/suncxx.py0000664000000000000000000000347212145745420014530 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_sxx(conf): """ Detect the sun C++ compiler """ v = conf.env cc = None if v['CXX']: cc = v['CXX'] elif 'CXX' in conf.environ: cc = conf.environ['CXX'] if not cc: cc = conf.find_program('CC', var='CXX') #studio if not cc: cc = conf.find_program('c++', var='CXX') if not cc: conf.fatal('Could not find a Sun C++ compiler') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-flags']) except Exception: conf.fatal('%r is not a Sun compiler' % cc) v['CXX'] = cc v['CXX_NAME'] = 'sun' @conf def sxx_common_flags(conf): """ Flags required for executing the sun C++ compiler """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STLIB_MARKER'] = '-Bstatic' # program v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-Kpic', '-DPIC'] v['LINKFLAGS_cxxshlib'] = ['-G'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = ['-Bstatic'] v['cxxstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_sxx() conf.find_ar() conf.sxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/qt4.py0000664000000000000000000004746112145745420013716 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Tool Description ================ This tool helps with finding Qt4 tools and libraries, and also provides syntactic sugar for using Qt4 tools. The following snippet illustrates the tool usage:: def options(opt): opt.load('compiler_cxx qt4') def configure(conf): conf.load('compiler_cxx qt4') def build(bld): bld( features = 'qt4 cxx cxxprogram', uselib = 'QTCORE QTGUI QTOPENGL QTSVG', source = 'main.cpp textures.qrc aboutDialog.ui', target = 'window', ) Here, the UI description and resource files will be processed to generate code. Usage ===== Load the "qt4" tool. You also need to edit your sources accordingly: - the normal way of doing things is to have your C++ files include the .moc file. This is regarded as the best practice (and provides much faster compilations). It also implies that the include paths have beenset properly. - to have the include paths added automatically, use the following:: from waflib.TaskGen import feature, before_method, after_method @feature('cxx') @after_method('process_source') @before_method('apply_incpaths') def add_includes_paths(self): incs = set(self.to_list(getattr(self, 'includes', ''))) for x in self.compiled_tasks: incs.add(x.inputs[0].parent.path_from(self.path)) self.includes = list(incs) Note: another tool provides Qt processing that does not require .moc includes, see ``playground/slow_qt/``self. A few options (--qt{dir,bin,...}) and environment variables (QT4_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, tool path selection, etc; please read the source for more info. """ try: from xml.sax import make_parser from xml.sax.handler import ContentHandler except ImportError: has_xml = False ContentHandler = object else: has_xml = True import os, sys from waflib.Tools import c_preproc, cxx from waflib import Task, Utils, Options, Errors from waflib.TaskGen import feature, after_method, extension from waflib.Configure import conf from waflib import Logs MOC_H = ['.h', '.hpp', '.hxx', '.hh'] """ File extensions associated to the .moc files """ EXT_RCC = ['.qrc'] """ File extension for the resource (.qrc) files """ EXT_UI = ['.ui'] """ File extension for the user interface (.ui) files """ EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] """ File extensions of C++ files that may require a .moc processing """ QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative" class qxx(cxx.cxx): """ Each C++ file can have zero or several .moc files to create. They are known only when the files are scanned (preprocessor) To avoid scanning the c++ files each time (parsing C/C++), the results are retrieved from the task cache (bld.node_deps/bld.raw_deps). The moc tasks are also created *dynamically* during the build. """ def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.moc_done = 0 def scan(self): """Re-use the C/C++ scanner, but remove the moc files from the dependencies""" (nodes, names) = c_preproc.scan(self) # for some reasons (variants) the moc node may end in the list of node deps for x in nodes: if x.name.endswith('.moc'): nodes.remove(x) names.append(x.path_from(self.inputs[0].parent.get_bld())) return (nodes, names) def runnable_status(self): """ Compute the task signature to make sure the scanner was executed. Create the moc tasks by using :py:meth:`waflib.Tools.qt4.qxx.add_moc_tasks` (if necessary), then postpone the task execution (there is no need to recompute the task signature). """ if self.moc_done: return Task.Task.runnable_status(self) else: for t in self.run_after: if not t.hasrun: return Task.ASK_LATER self.add_moc_tasks() return Task.Task.runnable_status(self) def add_moc_tasks(self): """ Create the moc tasks by looking in ``bld.raw_deps[self.uid()]`` """ node = self.inputs[0] bld = self.generator.bld try: # compute the signature once to know if there is a moc file to create self.signature() except KeyError: # the moc file may be referenced somewhere else pass else: # remove the signature, it must be recomputed with the moc task delattr(self, 'cache_sig') moctasks=[] mocfiles=[] try: tmp_lst = bld.raw_deps[self.uid()] bld.raw_deps[self.uid()] = [] except KeyError: tmp_lst = [] for d in tmp_lst: if not d.endswith('.moc'): continue # paranoid check if d in mocfiles: Logs.error("paranoia owns") continue # process that base.moc only once mocfiles.append(d) # find the extension - this search is done only once h_node = None try: ext = Options.options.qt_header_ext.split() except AttributeError: pass if not ext: ext = MOC_H base2 = d[:-4] for x in [node.parent] + self.generator.includes_nodes: for e in ext: h_node = x.find_node(base2 + e) if h_node: break if h_node: m_node = h_node.change_ext('.moc') break else: for k in EXT_QT4: if base2.endswith(k): for x in [node.parent] + self.generator.includes_nodes: h_node = x.find_node(base2) if h_node: break if h_node: m_node = h_node.change_ext(k + '.moc') break if not h_node: raise Errors.WafError('no header found for %r which is a moc file' % d) # next time we will not search for the extension (look at the 'for' loop below) bld.node_deps[(self.inputs[0].parent.abspath(), m_node.name)] = h_node # create the task task = Task.classes['moc'](env=self.env, generator=self.generator) task.set_inputs(h_node) task.set_outputs(m_node) # direct injection in the build phase (safe because called from the main thread) gen = bld.producer gen.outstanding.insert(0, task) gen.total += 1 moctasks.append(task) # remove raw deps except the moc files to save space (optimization) tmp_lst = bld.raw_deps[self.uid()] = mocfiles # look at the file inputs, it is set right above lst = bld.node_deps.get(self.uid(), ()) for d in lst: name = d.name if name.endswith('.moc'): task = Task.classes['moc'](env=self.env, generator=self.generator) task.set_inputs(bld.node_deps[(self.inputs[0].parent.abspath(), name)]) # 1st element in a tuple task.set_outputs(d) gen = bld.producer gen.outstanding.insert(0, task) gen.total += 1 moctasks.append(task) # simple scheduler dependency: run the moc task before others self.run_after.update(set(moctasks)) self.moc_done = 1 run = Task.classes['cxx'].__dict__['run'] class trans_update(Task.Task): """Update a .ts files from a list of C++ files""" run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' color = 'BLUE' Task.update_outputs(trans_update) class XMLHandler(ContentHandler): """ Parser for *.qrc* files """ def __init__(self): self.buf = [] self.files = [] def startElement(self, name, attrs): if name == 'file': self.buf = [] def endElement(self, name): if name == 'file': self.files.append(str(''.join(self.buf))) def characters(self, cars): self.buf.append(cars) @extension(*EXT_RCC) def create_rcc_task(self, node): "Create rcc and cxx tasks for *.qrc* files" rcnode = node.change_ext('_rc.cpp') rcctask = self.create_task('rcc', node, rcnode) cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) try: self.compiled_tasks.append(cpptask) except AttributeError: self.compiled_tasks = [cpptask] return cpptask @extension(*EXT_UI) def create_uic_task(self, node): "hook for uic tasks" uictask = self.create_task('ui4', node) uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])] @extension('.ts') def add_lang(self, node): """add all the .ts file into self.lang""" self.lang = self.to_list(getattr(self, 'lang', [])) + [node] @feature('qt4') @after_method('apply_link') def apply_qt4(self): """ Add MOC_FLAGS which may be necessary for moc:: def build(bld): bld.program(features='qt4', source='main.cpp', target='app', use='QTCORE') The additional parameters are: :param lang: list of translation files (\*.ts) to process :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension :param update: whether to process the C++ files to update the \*.ts files (use **waf --translate**) :type update: bool :param langname: if given, transform the \*.ts files into a .qrc files to include in the binary file :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension """ if getattr(self, 'lang', None): qmtasks = [] for x in self.to_list(self.lang): if isinstance(x, str): x = self.path.find_resource(x + '.ts') qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) if getattr(self, 'update', None) and Options.options.trans_qt4: cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')] for x in qmtasks: self.create_task('trans_update', cxxnodes, x.inputs) if getattr(self, 'langname', None): qmnodes = [x.outputs[0] for x in qmtasks] rcnode = self.langname if isinstance(rcnode, str): rcnode = self.path.find_or_declare(rcnode + '.qrc') t = self.create_task('qm2rcc', qmnodes, rcnode) k = create_rcc_task(self, t.outputs[0]) self.link_task.inputs.append(k.outputs[0]) lst = [] for flag in self.to_list(self.env['CXXFLAGS']): if len(flag) < 2: continue f = flag[0:2] if f in ['-D', '-I', '/D', '/I']: if (f[0] == '/'): lst.append('-' + flag[1:]) else: lst.append(flag) self.env['MOC_FLAGS'] = lst @extension(*EXT_QT4) def cxx_hook(self, node): """ Re-map C++ file extensions to the :py:class:`waflib.Tools.qt4.qxx` task. """ return self.create_compiled_task('qxx', node) class rcc(Task.Task): """ Process *.qrc* files """ color = 'BLUE' run_str = '${QT_RCC} -name ${SRC[0].name} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' ext_out = ['.h'] def scan(self): """Parse the *.qrc* files""" node = self.inputs[0] if not has_xml: Logs.error('no xml support was found, the rcc dependencies will be incomplete!') return ([], []) parser = make_parser() curHandler = XMLHandler() parser.setContentHandler(curHandler) fi = open(self.inputs[0].abspath(), 'r') try: parser.parse(fi) finally: fi.close() nodes = [] names = [] root = self.inputs[0].parent for x in curHandler.files: nd = root.find_resource(x) if nd: nodes.append(nd) else: names.append(x) return (nodes, names) class moc(Task.Task): """ Create *.moc* files """ color = 'BLUE' run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' class ui4(Task.Task): """ Process *.ui* files """ color = 'BLUE' run_str = '${QT_UIC} ${SRC} -o ${TGT}' ext_out = ['.h'] class ts2qm(Task.Task): """ Create *.qm* files from *.ts* files """ color = 'BLUE' run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' class qm2rcc(Task.Task): """ Transform *.qm* files into *.rc* files """ color = 'BLUE' after = 'ts2qm' def run(self): """Create a qrc file including the inputs""" txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) code = '\n\n%s\n\n' % txt self.outputs[0].write(code) def configure(self): """ Besides the configuration options, the environment variable QT4_ROOT may be used to give the location of the qt4 libraries (absolute path). The detection will use the program *pkg-config* through :py:func:`waflib.Tools.config_c.check_cfg` """ self.find_qt4_binaries() self.set_qt4_libs_to_check() self.find_qt4_libraries() self.add_qt4_rpath() self.simplify_qt4_libs() @conf def find_qt4_binaries(self): env = self.env opt = Options.options qtdir = getattr(opt, 'qtdir', '') qtbin = getattr(opt, 'qtbin', '') paths = [] if qtdir: qtbin = os.path.join(qtdir, 'bin') # the qt directory has been given from QT4_ROOT - deduce the qt binary path if not qtdir: qtdir = os.environ.get('QT4_ROOT', '') qtbin = os.environ.get('QT4_BIN', None) or os.path.join(qtdir, 'bin') if qtbin: paths = [qtbin] # no qtdir, look in the path and in /usr/local/Trolltech if not qtdir: paths = os.environ.get('PATH', '').split(os.pathsep) paths.append('/usr/share/qt4/bin/') try: lst = Utils.listdir('/usr/local/Trolltech/') except OSError: pass else: if lst: lst.sort() lst.reverse() # keep the highest version qtdir = '/usr/local/Trolltech/%s/' % lst[0] qtbin = os.path.join(qtdir, 'bin') paths.append(qtbin) # at the end, try to find qmake in the paths given # keep the one with the highest version cand = None prev_ver = ['4', '0', '0'] for qmk in ['qmake-qt4', 'qmake4', 'qmake']: try: qmake = self.find_program(qmk, path_list=paths) except self.errors.ConfigurationError: pass else: try: version = self.cmd_and_log([qmake, '-query', 'QT_VERSION']).strip() except self.errors.WafError: pass else: if version: new_ver = version.split('.') if new_ver > prev_ver: cand = qmake prev_ver = new_ver if cand: self.env.QMAKE = cand else: self.fatal('Could not find qmake for qt4') qtbin = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_BINS']).strip() + os.sep def find_bin(lst, var): if var in env: return for f in lst: try: ret = self.find_program(f, path_list=paths) except self.errors.ConfigurationError: pass else: env[var]=ret break find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') find_bin(['uic-qt4', 'uic'], 'QT_UIC') if not env['QT_UIC']: self.fatal('cannot find the uic compiler for qt4') try: uicver = self.cmd_and_log(env['QT_UIC'] + " -version 2>&1").strip() except self.errors.ConfigurationError: self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') self.msg('Checking for uic version', '%s' % uicver) if uicver.find(' 3.') != -1: self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') find_bin(['moc-qt4', 'moc'], 'QT_MOC') find_bin(['rcc'], 'QT_RCC') find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE') find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE') env['UIC3_ST']= '%s -o %s' env['UIC_ST'] = '%s -o %s' env['MOC_ST'] = '-o' env['ui_PATTERN'] = 'ui_%s.h' env['QT_LRELEASE_FLAGS'] = ['-silent'] env.MOCCPPPATH_ST = '-I%s' env.MOCDEFINES_ST = '-D%s' @conf def find_qt4_libraries(self): qtlibs = getattr(Options.options, 'qtlibs', None) or os.environ.get("QT4_LIBDIR", None) if not qtlibs: try: qtlibs = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_LIBS']).strip() except Errors.WafError: qtdir = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_PREFIX']).strip() + os.sep qtlibs = os.path.join(qtdir, 'lib') self.msg('Found the Qt4 libraries in', qtlibs) qtincludes = os.environ.get("QT4_INCLUDES", None) or self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_HEADERS']).strip() env = self.env if not 'PKG_CONFIG_PATH' in os.environ: os.environ['PKG_CONFIG_PATH'] = '%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib' % (qtlibs, qtlibs) try: if os.environ.get("QT4_XCOMPILE", None): raise self.errors.ConfigurationError() self.check_cfg(atleast_pkgconfig_version='0.1') except self.errors.ConfigurationError: for i in self.qt4_vars: uselib = i.upper() if Utils.unversioned_sys_platform() == "darwin": # Since at least qt 4.7.3 each library locates in separate directory frameworkName = i + ".framework" qtDynamicLib = os.path.join(qtlibs, frameworkName, i) if os.path.exists(qtDynamicLib): env.append_unique('FRAMEWORK_' + uselib, i) self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('INCLUDES_' + uselib, os.path.join(qtlibs, frameworkName, 'Headers')) elif env.DEST_OS != "win32": qtDynamicLib = os.path.join(qtlibs, "lib" + i + ".so") qtStaticLib = os.path.join(qtlibs, "lib" + i + ".a") if os.path.exists(qtDynamicLib): env.append_unique('LIB_' + uselib, i) self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') elif os.path.exists(qtStaticLib): env.append_unique('LIB_' + uselib, i) self.msg('Checking for %s' % i, qtStaticLib, 'GREEN') else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) else: # Release library names are like QtCore4 for k in ("lib%s.a", "lib%s4.a", "%s.lib", "%s4.lib"): lib = os.path.join(qtlibs, k % i) if os.path.exists(lib): env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) self.msg('Checking for %s' % i, lib, 'GREEN') break else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) # Debug library names are like QtCore4d uselib = i.upper() + "_debug" for k in ("lib%sd.a", "lib%sd4.a", "%sd.lib", "%sd4.lib"): lib = os.path.join(qtlibs, k % i) if os.path.exists(lib): env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) self.msg('Checking for %s' % i, lib, 'GREEN') break else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) else: for i in self.qt4_vars_debug + self.qt4_vars: self.check_cfg(package=i, args='--cflags --libs', mandatory=False) @conf def simplify_qt4_libs(self): # the libpaths make really long command-lines # remove the qtcore ones from qtgui, etc env = self.env def process_lib(vars_, coreval): for d in vars_: var = d.upper() if var == 'QTCORE': continue value = env['LIBPATH_'+var] if value: core = env[coreval] accu = [] for lib in value: if lib in core: continue accu.append(lib) env['LIBPATH_'+var] = accu process_lib(self.qt4_vars, 'LIBPATH_QTCORE') process_lib(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def add_qt4_rpath(self): # rpath if wanted env = self.env if Options.options.want_rpath: def process_rpath(vars_, coreval): for d in vars_: var = d.upper() value = env['LIBPATH_'+var] if value: core = env[coreval] accu = [] for lib in value: if var != 'QTCORE': if lib in core: continue accu.append('-Wl,--rpath='+lib) env['RPATH_'+var] = accu process_rpath(self.qt4_vars, 'LIBPATH_QTCORE') process_rpath(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def set_qt4_libs_to_check(self): if not hasattr(self, 'qt4_vars'): self.qt4_vars = QT4_LIBS self.qt4_vars = Utils.to_list(self.qt4_vars) if not hasattr(self, 'qt4_vars_debug'): self.qt4_vars_debug = [a + '_debug' for a in self.qt4_vars] self.qt4_vars_debug = Utils.to_list(self.qt4_vars_debug) def options(opt): """ Command-line options """ opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') opt.add_option('--header-ext', type='string', default='', help='header extension for moc files', dest='qt_header_ext') for i in 'qtdir qtbin qtlibs'.split(): opt.add_option('--'+i, type='string', default='', dest=i) opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) debian/waf-1.7/waflib/Tools/gxx.py0000664000000000000000000001020312145745420013774 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 """ g++/llvm detection. """ import os, sys from waflib import Configure, Options, Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_gxx(conf): """ Find the program g++, and if present, try to detect its version number """ cxx = conf.find_program(['g++', 'c++'], var='CXX') cxx = conf.cmd_to_list(cxx) conf.get_cc_version(cxx, gcc=True) conf.env.CXX_NAME = 'gcc' conf.env.CXX = cxx @conf def gxx_common_flags(conf): """ Common flags for g++ on nearly all platforms """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-fPIC'] v['LINKFLAGS_cxxshlib'] = ['-shared'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = ['-Wl,-Bstatic'] v['cxxstlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CXXFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conf def gxx_modifier_win32(conf): """Configuration flags for executing gcc on Windows""" v = conf.env v['cxxprogram_PATTERN'] = '%s.exe' v['cxxshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['CXXFLAGS_cxxshlib'] = [] # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gxx_modifier_cygwin(conf): """Configuration flags for executing g++ on Cygwin""" gxx_modifier_win32(conf) v = conf.env v['cxxshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_cxxshlib', ['-Wl,--enable-auto-image-base']) v['CXXFLAGS_cxxshlib'] = [] @conf def gxx_modifier_darwin(conf): """Configuration flags for executing g++ on MacOS""" v = conf.env v['CXXFLAGS_cxxshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_cxxshlib'] = ['-dynamiclib'] v['cxxshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = ['-framework'] v['ARCH_ST'] = ['-arch'] v['LINKFLAGS_cxxstlib'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] v['SONAME_ST'] = [] @conf def gxx_modifier_aix(conf): """Configuration flags for executing g++ on AIX""" v = conf.env v['LINKFLAGS_cxxprogram']= ['-Wl,-brtl'] v['LINKFLAGS_cxxshlib'] = ['-shared', '-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = [] @conf def gxx_modifier_hpux(conf): v = conf.env v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = '-Bstatic' v['CFLAGS_cxxshlib'] = ['-fPIC','-DPIC'] v['cxxshlib_PATTERN'] = 'lib%s.sl' @conf def gxx_modifier_platform(conf): """Execute platform-specific functions based on *gxx_modifier_+NAME*""" # * set configurations specific for a platform. # * the destination platform is detected automatically by looking at the macros the compiler predefines, # and if it's not recognised, it fallbacks to sys.platform. gxx_modifier_func = getattr(conf, 'gxx_modifier_' + conf.env.DEST_OS, None) if gxx_modifier_func: gxx_modifier_func() def configure(conf): """ Configuration for g++ """ conf.find_gxx() conf.find_ar() conf.gxx_common_flags() conf.gxx_modifier_platform() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/gcc.py0000664000000000000000000001014612145745420013730 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 """ gcc/llvm detection. """ import os, sys from waflib import Configure, Options, Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_gcc(conf): """ Find the program gcc, and if present, try to detect its version number """ cc = conf.find_program(['gcc', 'cc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_cc_version(cc, gcc=True) conf.env.CC_NAME = 'gcc' conf.env.CC = cc @conf def gcc_common_flags(conf): """ Common flags for gcc on nearly all platforms """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cprogram_PATTERN'] = '%s' # shared librar v['CFLAGS_cshlib'] = ['-fPIC'] v['LINKFLAGS_cshlib'] = ['-shared'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conf def gcc_modifier_win32(conf): """Configuration flags for executing gcc on Windows""" v = conf.env v['cprogram_PATTERN'] = '%s.exe' v['cshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['CFLAGS_cshlib'] = [] # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gcc_modifier_cygwin(conf): """Configuration flags for executing gcc on Cygwin""" gcc_modifier_win32(conf) v = conf.env v['cshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_cshlib', ['-Wl,--enable-auto-image-base']) v['CFLAGS_cshlib'] = [] @conf def gcc_modifier_darwin(conf): """Configuration flags for executing gcc on MacOS""" v = conf.env v['CFLAGS_cshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_cshlib'] = ['-dynamiclib'] v['cshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = ['-framework'] v['ARCH_ST'] = ['-arch'] v['LINKFLAGS_cstlib'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] v['SONAME_ST'] = [] @conf def gcc_modifier_aix(conf): """Configuration flags for executing gcc on AIX""" v = conf.env v['LINKFLAGS_cprogram'] = ['-Wl,-brtl'] v['LINKFLAGS_cshlib'] = ['-shared','-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = [] @conf def gcc_modifier_hpux(conf): v = conf.env v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = '-Bstatic' v['CFLAGS_cshlib'] = ['-fPIC','-DPIC'] v['cshlib_PATTERN'] = 'lib%s.sl' @conf def gcc_modifier_platform(conf): """Execute platform-specific functions based on *gcc_modifier_+NAME*""" # * set configurations specific for a platform. # * the destination platform is detected automatically by looking at the macros the compiler predefines, # and if it's not recognised, it fallbacks to sys.platform. gcc_modifier_func = getattr(conf, 'gcc_modifier_' + conf.env.DEST_OS, None) if gcc_modifier_func: gcc_modifier_func() def configure(conf): """ Configuration for gcc """ conf.find_gcc() conf.find_ar() conf.gcc_common_flags() conf.gcc_modifier_platform() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/flex.py0000664000000000000000000000243112145745420014130 0ustar #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy, 2006-2010 (ita) """ The **flex** program is a code generator which creates C or C++ files. The generated files are compiled into object files. """ import waflib.TaskGen, os, re def decide_ext(self, node): if 'cxx' in self.features: return ['.lex.cc'] return ['.lex.c'] def flexfun(tsk): env = tsk.env bld = tsk.generator.bld wd = bld.variant_dir def to_list(xx): if isinstance(xx, str): return [xx] return xx tsk.last_cmd = lst = [] lst.extend(to_list(env['FLEX'])) lst.extend(to_list(env['FLEXFLAGS'])) inputs = [a.path_from(bld.bldnode) for a in tsk.inputs] if env.FLEX_MSYS: inputs = [x.replace(os.sep, '/') for x in inputs] lst.extend(inputs) lst = [x for x in lst if x] txt = bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) tsk.outputs[0].write(txt.replace('\r\n', '\n').replace('\r', '\n')) # issue #1207 waflib.TaskGen.declare_chain( name = 'flex', rule = flexfun, # issue #854 ext_in = '.l', decider = decide_ext, ) def configure(conf): """ Detect the *flex* program """ conf.find_program('flex', var='FLEX') conf.env.FLEXFLAGS = ['-t'] if re.search (r"\\msys\\[0-9.]+\\bin\\flex.exe$", conf.env.FLEX): # this is the flex shipped with MSYS conf.env.FLEX_MSYS = True debian/waf-1.7/waflib/Tools/ifort.py0000664000000000000000000000270512145745420014321 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan, ar from waflib.Configure import conf @conf def find_ifort(conf): fc = conf.find_program('ifort', var='FC') fc = conf.cmd_to_list(fc) conf.get_ifort_version(fc) conf.env.FC_NAME = 'IFORT' @conf def ifort_modifier_cygwin(conf): raise NotImplementedError("Ifort on cygwin not yet implemented") @conf def ifort_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def ifort_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def ifort_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() ifort_modifier_func = getattr(conf, 'ifort_modifier_' + dest_os, None) if ifort_modifier_func: ifort_modifier_func() @conf def get_ifort_version(conf, fc): """get the compiler version""" version_re = re.compile(r"ifort\s*\(IFORT\)\s*(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('cannot determine ifort version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_ifort() conf.find_program('xiar', var='AR') conf.env.ARFLAGS = 'rcs' conf.fc_flags() conf.fc_add_flags() conf.ifort_modifier_platform() debian/waf-1.7/waflib/Tools/gdc.py0000664000000000000000000000235612145745420013735 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) import sys from waflib.Tools import ar, d from waflib.Configure import conf @conf def find_gdc(conf): """ Find the program gdc and set the variable *D* """ conf.find_program('gdc', var='D') out = conf.cmd_and_log([conf.env.D, '--version']) if out.find("gdc ") == -1: conf.fatal("detected compiler is not gdc") @conf def common_flags_gdc(conf): """ Set the flags required by *gdc* """ v = conf.env # _DFLAGS _DIMPORTFLAGS # for mory info about the meaning of this dict see dmd.py v['DFLAGS'] = [] v['D_SRC_F'] = ['-c'] v['D_TGT_F'] = '-o%s' # linker v['D_LINKER'] = v['D'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-o%s' v['DINC_ST'] = '-I%s' v['DSHLIB_MARKER'] = v['DSTLIB_MARKER'] = '' v['DSTLIB_ST'] = v['DSHLIB_ST'] = '-l%s' v['DSTLIBPATH_ST'] = v['DLIBPATH_ST'] = '-L%s' v['LINKFLAGS_dshlib'] = ['-shared'] v['DHEADER_ext'] = '.di' v.DFLAGS_d_with_header = '-fintfc' v['D_HDR_F'] = '-fintfc-file=%s' def configure(conf): """ Configuration for gdc """ conf.find_gdc() conf.load('ar') conf.load('d') conf.common_flags_gdc() conf.d_platform_flags() debian/waf-1.7/waflib/Tools/xlc.py0000664000000000000000000000311412145745420013757 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_xlc(conf): """ Detect the Aix C compiler """ cc = conf.find_program(['xlc_r', 'xlc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_xlc_version(cc) conf.env.CC_NAME = 'xlc' conf.env.CC = cc @conf def xlc_common_flags(conf): """ Flags required for executing the Aix C compiler """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] # program v['LINKFLAGS_cprogram'] = ['-Wl,-brtl'] v['cprogram_PATTERN'] = '%s' # shared library v['CFLAGS_cshlib'] = ['-fPIC'] v['LINKFLAGS_cshlib'] = ['-G', '-Wl,-brtl,-bexpfull'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = [] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_xlc() conf.find_ar() conf.xlc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/tex.py0000664000000000000000000002753012145745420014001 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ TeX/LaTeX/PDFLaTeX/XeLaTeX support Example:: def configure(conf): conf.load('tex') if not conf.env.LATEX: conf.fatal('The program LaTex is required') def build(bld): bld( features = 'tex', type = 'latex', # pdflatex or xelatex source = 'document.ltx', # mandatory, the source outs = 'ps', # 'pdf' or 'ps pdf' deps = 'crossreferencing.lst', # to give dependencies directly prompt = 1, # 0 for the batch mode ) To configure with a special program use:: $ PDFLATEX=luatex waf configure """ import os, re from waflib import Utils, Task, Errors, Logs from waflib.TaskGen import feature, before_method re_bibunit = re.compile(r'\\(?Pputbib)\[(?P[^\[\]]*)\]',re.M) def bibunitscan(self): """ Parse the inputs and try to find the *bibunit* dependencies :return: list of bibunit files :rtype: list of :py:class:`waflib.Node.Node` """ node = self.inputs[0] nodes = [] if not node: return nodes code = node.read() for match in re_bibunit.finditer(code): path = match.group('file') if path: for k in ['', '.bib']: # add another loop for the tex include paths? Logs.debug('tex: trying %s%s' % (path, k)) fi = node.parent.find_resource(path + k) if fi: nodes.append(fi) # no break, people are crazy else: Logs.debug('tex: could not find %s' % path) Logs.debug("tex: found the following bibunit files: %s" % nodes) return nodes exts_deps_tex = ['', '.ltx', '.tex', '.bib', '.pdf', '.png', '.eps', '.ps'] """List of typical file extensions included in latex files""" exts_tex = ['.ltx', '.tex'] """List of typical file extensions that contain latex""" re_tex = re.compile(r'\\(?Pinclude|bibliography|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P[^{}]*)}',re.M) """Regexp for expressions that may include latex files""" g_bibtex_re = re.compile('bibdata', re.M) """Regexp for bibtex files""" class tex(Task.Task): """ Compile a tex/latex file. .. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex """ bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) bibtex_fun.__doc__ = """ Execute the program **bibtex** """ makeindex_fun, _ = Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) makeindex_fun.__doc__ = """ Execute the program **makeindex** """ def exec_command(self, cmd, **kw): """ Override :py:meth:`waflib.Task.Task.exec_command` to execute the command without buffering (latex may prompt for inputs) :return: the return code :rtype: int """ bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir return Utils.subprocess.Popen(cmd, **kw).wait() def scan_aux(self, node): """ A recursive regex-based scanner that finds included auxiliary files. """ nodes = [node] re_aux = re.compile(r'\\@input{(?P[^{}]*)}', re.M) def parse_node(node): code = node.read() for match in re_aux.finditer(code): path = match.group('file') found = node.parent.find_or_declare(path) if found and found not in nodes: Logs.debug('tex: found aux node ' + found.abspath()) nodes.append(found) parse_node(found) parse_node(node) return nodes def scan(self): """ A recursive regex-based scanner that finds latex dependencies. It uses :py:attr:`waflib.Tools.tex.re_tex` Depending on your needs you might want: * to change re_tex:: from waflib.Tools import tex tex.re_tex = myregex * or to change the method scan from the latex tasks:: from waflib.Task import classes classes['latex'].scan = myscanfunction """ node = self.inputs[0] nodes = [] names = [] seen = [] if not node: return (nodes, names) def parse_node(node): if node in seen: return seen.append(node) code = node.read() global re_tex for match in re_tex.finditer(code): for path in match.group('file').split(','): if path: add_name = True found = None for k in exts_deps_tex: Logs.debug('tex: trying %s%s' % (path, k)) found = node.parent.find_resource(path + k) for tsk in self.generator.tasks: if not found or found in tsk.outputs: break else: nodes.append(found) add_name = False for ext in exts_tex: if found.name.endswith(ext): parse_node(found) break # no break, people are crazy if add_name: names.append(path) parse_node(node) for x in nodes: x.parent.get_bld().mkdir() Logs.debug("tex: found the following : %s and names %s" % (nodes, names)) return (nodes, names) def check_status(self, msg, retcode): """ Check an exit status and raise an error with a particular message :param msg: message to display if the code is non-zero :type msg: string :param retcode: condition :type retcode: boolean """ if retcode != 0: raise Errors.WafError("%r command exit status %r" % (msg, retcode)) def bibfile(self): """ Parse the *.aux* files to find a bibfile to process. If yes, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun` """ need_bibtex = False try: for aux_node in self.aux_nodes: ct = aux_node.read() if g_bibtex_re.findall(ct): need_bibtex = True break except (OSError, IOError): Logs.error('error bibtex scan') else: # only the main .aux file needs to be processed if need_bibtex: Logs.warn('calling bibtex') self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS}) self.env.SRCFILE = self.aux_nodes[0].name[:-4] self.check_status('error when calling bibtex', self.bibtex_fun()) def bibunits(self): """ Parse the *.aux* file to find bibunit files. If there are bibunit files, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun`. """ try: bibunits = bibunitscan(self) except OSError: Logs.error('error bibunitscan') else: if bibunits: fn = ['bu' + str(i) for i in xrange(1, len(bibunits) + 1)] if fn: Logs.warn('calling bibtex on bibunits') for f in fn: self.env.env = {'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS} self.env.SRCFILE = f self.check_status('error when calling bibtex', self.bibtex_fun()) def makeindex(self): """ Look on the filesystem if there is a *.idx* file to process. If yes, execute :py:meth:`waflib.Tools.tex.tex.makeindex_fun` """ try: idx_path = self.idx_node.abspath() os.stat(idx_path) except OSError: Logs.warn('index file %s absent, not calling makeindex' % idx_path) else: Logs.warn('calling makeindex') self.env.SRCFILE = self.idx_node.name self.env.env = {} self.check_status('error when calling makeindex %s' % idx_path, self.makeindex_fun()) def run(self): """ Runs the TeX build process. It may require multiple passes, depending on the usage of cross-references, bibliographies, content susceptible of needing such passes. The appropriate TeX compiler is called until the *.aux* files stop changing. Makeindex and bibtex are called if necessary. """ env = self.env if not env['PROMPT_LATEX']: env.append_value('LATEXFLAGS', '-interaction=batchmode') env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') env.append_value('XELATEXFLAGS', '-interaction=batchmode') fun = self.texfun node = self.inputs[0] srcfile = node.abspath() texinputs = self.env.TEXINPUTS or '' self.TEXINPUTS = node.parent.get_bld().abspath() + os.pathsep + node.parent.get_src().abspath() + os.pathsep + texinputs + os.pathsep # important, set the cwd for everybody self.cwd = self.inputs[0].parent.get_bld().abspath() Logs.warn('first pass on %s' % self.__class__.__name__) self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'TEXINPUTS': self.TEXINPUTS}) self.env.SRCFILE = srcfile self.check_status('error when calling latex', fun()) self.aux_nodes = self.scan_aux(node.change_ext('.aux')) self.idx_node = node.change_ext('.idx') self.bibfile() self.bibunits() self.makeindex() hash = '' for i in range(10): # prevent against infinite loops - one never knows # watch the contents of file.aux and stop if file.aux does not change anymore prev_hash = hash try: hashes = [Utils.h_file(x.abspath()) for x in self.aux_nodes] hash = Utils.h_list(hashes) except (OSError, IOError): Logs.error('could not read aux.h') pass if hash and hash == prev_hash: break # run the command Logs.warn('calling %s' % self.__class__.__name__) self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'TEXINPUTS': self.TEXINPUTS}) self.env.SRCFILE = srcfile self.check_status('error when calling %s' % self.__class__.__name__, fun()) class latex(tex): texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) class pdflatex(tex): texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) class xelatex(tex): texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) class dvips(Task.Task): run_str = '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] class dvipdf(Task.Task): run_str = '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] class pdf2ps(Task.Task): run_str = '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] @feature('tex') @before_method('process_source') def apply_tex(self): """ Create :py:class:`waflib.Tools.tex.tex` objects, and dvips/dvipdf/pdf2ps tasks if necessary (outs='ps', etc). """ if not getattr(self, 'type', None) in ['latex', 'pdflatex', 'xelatex']: self.type = 'pdflatex' tree = self.bld outs = Utils.to_list(getattr(self, 'outs', [])) # prompt for incomplete files (else the batchmode is used) self.env['PROMPT_LATEX'] = getattr(self, 'prompt', 1) deps_lst = [] if getattr(self, 'deps', None): deps = self.to_list(self.deps) for filename in deps: n = self.path.find_resource(filename) if not n: self.bld.fatal('Could not find %r for %r' % (filename, self)) if not n in deps_lst: deps_lst.append(n) for node in self.to_nodes(self.source): if self.type == 'latex': task = self.create_task('latex', node, node.change_ext('.dvi')) elif self.type == 'pdflatex': task = self.create_task('pdflatex', node, node.change_ext('.pdf')) elif self.type == 'xelatex': task = self.create_task('xelatex', node, node.change_ext('.pdf')) task.env = self.env # add the manual dependencies if deps_lst: try: lst = tree.node_deps[task.uid()] for n in deps_lst: if not n in lst: lst.append(n) except KeyError: tree.node_deps[task.uid()] = deps_lst v = dict(os.environ) p = node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.get_bld().abspath() + os.pathsep + v.get('TEXINPUTS', '') + os.pathsep v['TEXINPUTS'] = p if self.type == 'latex': if 'ps' in outs: tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) tsk.env.env = dict(v) if 'pdf' in outs: tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) tsk.env.env = dict(v) elif self.type == 'pdflatex': if 'ps' in outs: self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) self.source = [] def configure(self): """ Try to find the programs tex, latex and others. Do not raise any error if they are not found. """ v = self.env for p in 'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): try: self.find_program(p, var=p.upper()) except self.errors.ConfigurationError: pass v['DVIPSFLAGS'] = '-Ppdf' debian/waf-1.7/waflib/Tools/vala.py0000664000000000000000000002467412145745420014132 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 # Radosław Szkodziński, 2010 """ At this point, vala is still unstable, so do not expect this tool to be too stable either (apis, etc) """ import os.path, shutil, re from waflib import Context, Task, Utils, Logs, Options, Errors from waflib.TaskGen import extension, taskgen_method from waflib.Configure import conf class valac(Task.Task): """ Task to compile vala files. """ #run_str = "${VALAC} ${VALAFLAGS}" # ideally #vars = ['VALAC_VERSION'] vars = ["VALAC", "VALAC_VERSION", "VALAFLAGS"] ext_out = ['.h'] def run(self): cmd = [self.env['VALAC']] + self.env['VALAFLAGS'] cmd.extend([a.abspath() for a in self.inputs]) ret = self.exec_command(cmd, cwd=self.outputs[0].parent.abspath()) if ret: return ret for x in self.outputs: if id(x.parent) != id(self.outputs[0].parent): shutil.move(self.outputs[0].parent.abspath() + os.sep + x.name, x.abspath()) if self.generator.dump_deps_node: self.generator.dump_deps_node.write('\n'.join(self.generator.packages)) return ret valac = Task.update_outputs(valac) # no decorators for python2 classes @taskgen_method def init_vala_task(self): self.profile = getattr(self, 'profile', 'gobject') if self.profile == 'gobject': self.uselib = Utils.to_list(getattr(self, 'uselib', [])) if not 'GOBJECT' in self.uselib: self.uselib.append('GOBJECT') def addflags(flags): self.env.append_value('VALAFLAGS', flags) if self.profile: addflags('--profile=%s' % self.profile) if hasattr(self, 'threading'): if self.profile == 'gobject': if not 'GTHREAD' in self.uselib: self.uselib.append('GTHREAD') else: #Vala doesn't have threading support for dova nor posix Logs.warn("Profile %s means no threading support" % self.profile) self.threading = False if self.threading: addflags('--threading') valatask = self.valatask self.is_lib = 'cprogram' not in self.features if self.is_lib: addflags('--library=%s' % self.target) h_node = self.path.find_or_declare('%s.h' % self.target) valatask.outputs.append(h_node) addflags('--header=%s' % h_node.name) valatask.outputs.append(self.path.find_or_declare('%s.vapi' % self.target)) if getattr(self, 'gir', None): gir_node = self.path.find_or_declare('%s.gir' % self.gir) addflags('--gir=%s' % gir_node.name) valatask.outputs.append(gir_node) self.vala_target_glib = getattr(self, 'vala_target_glib', getattr(Options.options, 'vala_target_glib', None)) if self.vala_target_glib: addflags('--target-glib=%s' % self.vala_target_glib) addflags(['--define=%s' % x for x in getattr(self, 'vala_defines', [])]) packages_private = Utils.to_list(getattr(self, 'packages_private', [])) addflags(['--pkg=%s' % x for x in packages_private]) def _get_api_version(): api_version = '1.0' if hasattr(Context.g_module, 'API_VERSION'): version = Context.g_module.API_VERSION.split(".") if version[0] == "0": api_version = "0." + version[1] else: api_version = version[0] + ".0" return api_version self.includes = Utils.to_list(getattr(self, 'includes', [])) self.uselib = self.to_list(getattr(self, 'uselib', [])) valatask.install_path = getattr(self, 'install_path', '') valatask.vapi_path = getattr(self, 'vapi_path', '${DATAROOTDIR}/vala/vapi') valatask.pkg_name = getattr(self, 'pkg_name', self.env['PACKAGE']) valatask.header_path = getattr(self, 'header_path', '${INCLUDEDIR}/%s-%s' % (valatask.pkg_name, _get_api_version())) valatask.install_binding = getattr(self, 'install_binding', True) self.packages = packages = Utils.to_list(getattr(self, 'packages', [])) self.vapi_dirs = vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) includes = [] if hasattr(self, 'use'): local_packages = Utils.to_list(self.use)[:] # make sure to have a copy seen = [] while len(local_packages) > 0: package = local_packages.pop() if package in seen: continue seen.append(package) # check if the package exists try: package_obj = self.bld.get_tgen_by_name(package) except Errors.WafError: continue package_name = package_obj.target package_node = package_obj.path package_dir = package_node.path_from(self.path) for task in package_obj.tasks: for output in task.outputs: if output.name == package_name + ".vapi": valatask.set_run_after(task) if package_name not in packages: packages.append(package_name) if package_dir not in vapi_dirs: vapi_dirs.append(package_dir) if package_dir not in includes: includes.append(package_dir) if hasattr(package_obj, 'use'): lst = self.to_list(package_obj.use) lst.reverse() local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages addflags(['--pkg=%s' % p for p in packages]) for vapi_dir in vapi_dirs: v_node = self.path.find_dir(vapi_dir) if not v_node: Logs.warn('Unable to locate Vala API directory: %r' % vapi_dir) else: addflags('--vapidir=%s' % v_node.abspath()) addflags('--vapidir=%s' % v_node.get_bld().abspath()) self.dump_deps_node = None if self.is_lib and self.packages: self.dump_deps_node = self.path.find_or_declare('%s.deps' % self.target) valatask.outputs.append(self.dump_deps_node) self.includes.append(self.bld.srcnode.abspath()) self.includes.append(self.bld.bldnode.abspath()) for include in includes: try: self.includes.append(self.path.find_dir(include).abspath()) self.includes.append(self.path.find_dir(include).get_bld().abspath()) except AttributeError: Logs.warn("Unable to locate include directory: '%s'" % include) if self.is_lib and valatask.install_binding: headers_list = [o for o in valatask.outputs if o.suffix() == ".h"] try: self.install_vheader.source = headers_list except AttributeError: self.install_vheader = self.bld.install_files(valatask.header_path, headers_list, self.env) vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))] try: self.install_vapi.source = vapi_list except AttributeError: self.install_vapi = self.bld.install_files(valatask.vapi_path, vapi_list, self.env) gir_list = [o for o in valatask.outputs if o.suffix() == '.gir'] try: self.install_gir.source = gir_list except AttributeError: self.install_gir = self.bld.install_files(getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0'), gir_list, self.env) @extension('.vala', '.gs') def vala_file(self, node): """ Compile a vala file and bind the task to *self.valatask*. If an existing vala task is already set, add the node to its inputs. The typical example is:: def build(bld): bld.program( packages = 'gtk+-2.0', target = 'vala-gtk-example', uselib = 'GTK GLIB', source = 'vala-gtk-example.vala foo.vala', vala_defines = ['DEBUG'] # adds --define= values to the command-line # the following arguments are for libraries #gir = 'hello-1.0', #gir_path = '/tmp', #vapi_path = '/tmp', #pkg_name = 'hello' # disable installing of gir, vapi and header #install_binding = False # profile = 'xyz' # adds --profile= to enable profiling # threading = True, # add --threading, except if profile is on or not on 'gobject' # vala_target_glib = 'xyz' # adds --target-glib=, can be given through the command-line option --vala-target-glib= ) :param node: vala file :type node: :py:class:`waflib.Node.Node` """ try: valatask = self.valatask except AttributeError: valatask = self.valatask = self.create_task('valac') self.init_vala_task() valatask.inputs.append(node) c_node = node.change_ext('.c') valatask.outputs.append(c_node) self.source.append(c_node) @conf def find_valac(self, valac_name, min_version): """ Find the valac program, and execute it to store the version number in *conf.env.VALAC_VERSION* :param valac_name: program name :type valac_name: string or list of string :param min_version: minimum version acceptable :type min_version: tuple of int """ valac = self.find_program(valac_name, var='VALAC') try: output = self.cmd_and_log(valac + ' --version') except Exception: valac_version = None else: ver = re.search(r'\d+.\d+.\d+', output).group(0).split('.') valac_version = tuple([int(x) for x in ver]) self.msg('Checking for %s version >= %r' % (valac_name, min_version), valac_version, valac_version and valac_version >= min_version) if valac and valac_version < min_version: self.fatal("%s version %r is too old, need >= %r" % (valac_name, valac_version, min_version)) self.env['VALAC_VERSION'] = valac_version return valac @conf def check_vala(self, min_version=(0,8,0), branch=None): """ Check if vala compiler from a given branch exists of at least a given version. :param min_version: minimum version acceptable (0.8.0) :type min_version: tuple :param branch: first part of the version number, in case a snapshot is used (0, 8) :type branch: tuple of int """ if not branch: branch = min_version[:2] try: find_valac(self, 'valac-%d.%d' % (branch[0], branch[1]), min_version) except self.errors.ConfigurationError: find_valac(self, 'valac', min_version) @conf def check_vala_deps(self): """ Load the gobject and gthread packages if they are missing. """ if not self.env['HAVE_GOBJECT']: pkg_args = {'package': 'gobject-2.0', 'uselib_store': 'GOBJECT', 'args': '--cflags --libs'} if getattr(Options.options, 'vala_target_glib', None): pkg_args['atleast_version'] = Options.options.vala_target_glib self.check_cfg(**pkg_args) if not self.env['HAVE_GTHREAD']: pkg_args = {'package': 'gthread-2.0', 'uselib_store': 'GTHREAD', 'args': '--cflags --libs'} if getattr(Options.options, 'vala_target_glib', None): pkg_args['atleast_version'] = Options.options.vala_target_glib self.check_cfg(**pkg_args) def configure(self): """ Use the following to enforce minimum vala version:: def configure(conf): conf.load('vala', funs='') conf.check_vala(min_version=(0,10,0)) """ self.load('gnu_dirs') self.check_vala_deps() self.check_vala() self.env.VALAFLAGS = ['-C', '--quiet'] def options(opt): """ Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option """ opt.load('gnu_dirs') valaopts = opt.add_option_group('Vala Compiler Options') valaopts.add_option ('--vala-target-glib', default=None, dest='vala_target_glib', metavar='MAJOR.MINOR', help='Target version of glib for Vala GObject code generation') debian/waf-1.7/waflib/Tools/perl.py0000664000000000000000000001067012145745420014140 0ustar #!/usr/bin/env python # encoding: utf-8 # andersg at 0x63.nu 2007 # Thomas Nagy 2010 (ita) """ Support for Perl extensions. A C/C++ compiler is required:: def options(opt): opt.load('compiler_c perl') def configure(conf): conf.load('compiler_c perl') conf.check_perl_version((5,6,0)) conf.check_perl_ext_devel() conf.check_perl_module('Cairo') conf.check_perl_module('Devel::PPPort 4.89') def build(bld): bld( features = 'c cshlib perlext', source = 'Mytest.xs', target = 'Mytest', install_path = '${ARCHDIR_PERL}/auto') bld.install_files('${ARCHDIR_PERL}', 'Mytest.pm') """ import os from waflib import Task, Options, Utils from waflib.Configure import conf from waflib.TaskGen import extension, feature, before_method @before_method('apply_incpaths', 'apply_link', 'propagate_uselib_vars') @feature('perlext') def init_perlext(self): """ Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the *lib* prefix from library names. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PERLEXT' in self.uselib: self.uselib.append('PERLEXT') self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['perlext_PATTERN'] @extension('.xs') def xsubpp_file(self, node): """ Create :py:class:`waflib.Tools.perl.xsubpp` tasks to process *.xs* files """ outnode = node.change_ext('.c') self.create_task('xsubpp', node, outnode) self.source.append(outnode) class xsubpp(Task.Task): """ Process *.xs* files """ run_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' color = 'BLUE' ext_out = ['.h'] @conf def check_perl_version(self, minver=None): """ Check if Perl is installed, and set the variable PERL. minver is supposed to be a tuple """ res = True if minver: cver = '.'.join(map(str,minver)) else: cver = '' self.start_msg('Checking for minimum perl version %s' % cver) perl = getattr(Options.options, 'perlbinary', None) if not perl: perl = self.find_program('perl', var='PERL') if not perl: self.end_msg("Perl not found", color="YELLOW") return False self.env['PERL'] = perl version = self.cmd_and_log([perl, "-e", 'printf \"%vd\", $^V']) if not version: res = False version = "Unknown" elif not minver is None: ver = tuple(map(int, version.split("."))) if ver < minver: res = False self.end_msg(version, color=res and "GREEN" or "YELLOW") return res @conf def check_perl_module(self, module): """ Check if specified perlmodule is installed. The minimum version can be specified by specifying it after modulename like this:: def configure(conf): conf.check_perl_module("Some::Module 2.92") """ cmd = [self.env['PERL'], '-e', 'use %s' % module] self.start_msg('perl module %s' % module) try: r = self.cmd_and_log(cmd) except Exception: self.end_msg(False) return None self.end_msg(r or True) return r @conf def check_perl_ext_devel(self): """ Check for configuration needed to build perl extensions. Sets different xxx_PERLEXT variables in the environment. Also sets the ARCHDIR_PERL variable useful as installation path, which can be overridden by ``--with-perl-archdir`` option. """ env = self.env perl = env.PERL if not perl: self.fatal('find perl first') def read_out(cmd): return Utils.to_list(self.cmd_and_log(perl + cmd)) env['LINKFLAGS_PERLEXT'] = read_out(" -MConfig -e'print $Config{lddlflags}'") env['INCLUDES_PERLEXT'] = read_out(" -MConfig -e'print \"$Config{archlib}/CORE\"'") env['CFLAGS_PERLEXT'] = read_out(" -MConfig -e'print \"$Config{ccflags} $Config{cccdlflags}\"'") env['XSUBPP'] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}\"'") env['EXTUTILS_TYPEMAP'] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/typemap\"'") if not getattr(Options.options, 'perlarchdir', None): env['ARCHDIR_PERL'] = self.cmd_and_log(perl + " -MConfig -e'print $Config{sitearch}'") else: env['ARCHDIR_PERL'] = getattr(Options.options, 'perlarchdir') env['perlext_PATTERN'] = '%s.' + self.cmd_and_log(perl + " -MConfig -e'print $Config{dlext}'") def options(opt): """ Add the ``--with-perl-archdir`` and ``--with-perl-binary`` command-line options. """ opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) debian/waf-1.7/waflib/Tools/bison.py0000664000000000000000000000225512145745420014310 0ustar #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy 2009-2010 (ita) """ The **bison** program is a code generator which creates C or C++ files. The generated files are compiled into object files. """ from waflib import Task from waflib.TaskGen import extension class bison(Task.Task): """Compile bison files""" color = 'BLUE' run_str = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' ext_out = ['.h'] # just to make sure @extension('.y', '.yc', '.yy') def big_bison(self, node): """ Create a bison task, which must be executed from the directory of the output file. """ has_h = '-d' in self.env['BISONFLAGS'] outs = [] if node.name.endswith('.yc'): outs.append(node.change_ext('.tab.cc')) if has_h: outs.append(node.change_ext('.tab.hh')) else: outs.append(node.change_ext('.tab.c')) if has_h: outs.append(node.change_ext('.tab.h')) tsk = self.create_task('bison', node, outs) tsk.cwd = node.parent.get_bld().abspath() # and the c/cxx file must be compiled too self.source.append(outs[0]) def configure(conf): """ Detect the *bison* program """ conf.find_program('bison', var='BISON') conf.env.BISONFLAGS = ['-d'] debian/waf-1.7/waflib/Tools/compiler_cxx.py0000664000000000000000000000602312145745420015667 0ustar #!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) """ Try to detect a C++ compiler from the list of supported compilers (g++, msvc, etc):: def options(opt): opt.load('compiler_cxx') def configure(cnf): cnf.load('compiler_cxx') def build(bld): bld.program(source='main.cpp', target='app') The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_cxx.cxx_compiler`. To register a new C++ compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: def options(opt): opt.load('compiler_cxx') def configure(cnf): from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] cnf.load('compiler_cxx') def build(bld): bld.program(source='main.c', target='app') Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: $ CXX=clang waf configure """ import os, sys, imp, types from waflib.Tools import ccroot from waflib import Utils, Configure from waflib.Logs import debug cxx_compiler = { 'win32': ['msvc', 'g++'], 'cygwin': ['g++'], 'darwin': ['g++'], 'aix': ['xlc++', 'g++'], 'linux': ['g++', 'icpc'], 'sunos': ['sunc++', 'g++'], 'irix': ['g++'], 'hpux': ['g++'], 'gnu': ['g++'], 'java': ['g++', 'msvc', 'icpc'], 'default': ['g++'] } """ Dict mapping the platform names to waf tools finding specific compilers:: from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['linux'] = ['gxx', 'icpc', 'suncxx'] """ def configure(conf): """ Try to find a suitable C++ compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_cxx_compiler except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_cxx')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (c++ compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_cxx: %r' % e) else: if conf.env['CXX']: conf.end_msg(conf.env.get_flat('CXX')) conf.env['COMPILER_CXX'] = compiler break conf.end_msg(False) else: conf.fatal('could not configure a c++ compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-cxx-compiler=gxx """ opt.load_special_tools('cxx_*.py') global cxx_compiler build_platform = Utils.unversioned_sys_platform() possible_compiler_list = cxx_compiler[build_platform in cxx_compiler and build_platform or 'default'] test_for_compiler = ' '.join(possible_compiler_list) cxx_compiler_opts = opt.add_option_group('C++ Compiler Options') cxx_compiler_opts.add_option('--check-cxx-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C++ Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_cxx_compiler") for x in test_for_compiler.split(): opt.load('%s' % x) debian/waf-1.7/waflib/Tools/compiler_c.py0000664000000000000000000000575112145745420015316 0ustar #!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) """ Try to detect a C compiler from the list of supported compilers (gcc, msvc, etc):: def options(opt): opt.load('compiler_c') def configure(cnf): cnf.load('compiler_c') def build(bld): bld.program(source='main.c', target='app') The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_c.c_compiler`. To register a new C compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: def options(opt): opt.load('compiler_c') def configure(cnf): from waflib.Tools.compiler_c import c_compiler c_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] cnf.load('compiler_c') def build(bld): bld.program(source='main.c', target='app') Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: $ CC=clang waf configure """ import os, sys, imp, types from waflib.Tools import ccroot from waflib import Utils, Configure from waflib.Logs import debug c_compiler = { 'win32': ['msvc', 'gcc'], 'cygwin': ['gcc'], 'darwin': ['gcc'], 'aix': ['xlc', 'gcc'], 'linux': ['gcc', 'icc'], 'sunos': ['suncc', 'gcc'], 'irix': ['gcc', 'irixcc'], 'hpux': ['gcc'], 'gnu': ['gcc'], 'java': ['gcc', 'msvc', 'icc'], 'default':['gcc'], } """ Dict mapping the platform names to waf tools finding specific compilers:: from waflib.Tools.compiler_c import c_compiler c_compiler['linux'] = ['gcc', 'icc', 'suncc'] """ def configure(conf): """ Try to find a suitable C compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_c_compiler except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_c')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (c compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_c: %r' % e) else: if conf.env['CC']: conf.end_msg(conf.env.get_flat('CC')) conf.env['COMPILER_CC'] = compiler break conf.end_msg(False) else: conf.fatal('could not configure a c compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-c-compiler=gcc """ opt.load_special_tools('c_*.py', ban=['c_dumbpreproc.py']) global c_compiler build_platform = Utils.unversioned_sys_platform() possible_compiler_list = c_compiler[build_platform in c_compiler and build_platform or 'default'] test_for_compiler = ' '.join(possible_compiler_list) cc_compiler_opts = opt.add_option_group("C Compiler Options") cc_compiler_opts.add_option('--check-c-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C-Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_c_compiler") for x in test_for_compiler.split(): opt.load('%s' % x) debian/waf-1.7/waflib/Tools/python.py0000664000000000000000000004216512145745420014523 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) # Gustavo Carneiro (gjc), 2007 """ Support for Python, detect the headers and libraries and provide *use* variables to link C/C++ programs against them:: def options(opt): opt.load('compiler_c python') def configure(conf): conf.load('compiler_c python') conf.check_python_version((2,4,2)) conf.check_python_headers() def build(bld): bld.program(features='pyembed', source='a.c', target='myprog') bld.shlib(features='pyext', source='b.c', target='mylib') """ import os, sys from waflib import Utils, Options, Errors, Logs from waflib.TaskGen import extension, before_method, after_method, feature from waflib.Configure import conf FRAG = ''' #include #ifdef __cplusplus extern "C" { #endif void Py_Initialize(void); void Py_Finalize(void); #ifdef __cplusplus } #endif int main(int argc, char **argv) { (void)argc; (void)argv; Py_Initialize(); Py_Finalize(); return 0; } ''' """ Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers` """ INST = ''' import sys, py_compile py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3]) ''' """ Piece of Python code used in :py:func:`waflib.Tools.python.install_pyfile` for installing python files """ DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib'] @extension('.py') def process_py(self, node): """ Add a callback using :py:func:`waflib.Tools.python.install_pyfile` to install a python file """ try: if not self.bld.is_install: return except AttributeError: return try: if not self.install_path: return except AttributeError: self.install_path = '${PYTHONDIR}' # i wonder now why we wanted to do this after the build is over # issue #901: people want to preserve the structure of installed files def inst_py(ctx): install_from = getattr(self, 'install_from', None) if install_from: install_from = self.path.find_dir(install_from) install_pyfile(self, node, install_from) self.bld.add_post_fun(inst_py) def install_pyfile(self, node, install_from=None): """ Execute the installation of a python file :param node: python file :type node: :py:class:`waflib.Node.Node` """ from_node = install_from or node.parent tsk = self.bld.install_as(self.install_path + '/' + node.path_from(from_node), node, postpone=False) path = tsk.get_install_path() if self.bld.is_install < 0: Logs.info("+ removing byte compiled python files") for x in 'co': try: os.remove(path + x) except OSError: pass if self.bld.is_install > 0: try: st1 = os.stat(path) except OSError: Logs.error('The python file is missing, this should not happen') for x in ['c', 'o']: do_inst = self.env['PY' + x.upper()] try: st2 = os.stat(path + x) except OSError: pass else: if st1.st_mtime <= st2.st_mtime: do_inst = False if do_inst: lst = (x == 'o') and [self.env['PYFLAGS_OPT']] or [] (a, b, c) = (path, path + x, tsk.get_install_path(destdir=False) + x) argv = self.env['PYTHON'] + lst + ['-c', INST, a, b, c] Logs.info('+ byte compiling %r' % (path + x)) env = self.env.env or None ret = Utils.subprocess.Popen(argv, env=env).wait() if ret: raise Errors.WafError('py%s compilation failed %r' % (x, path)) @feature('py') def feature_py(self): """ Dummy feature which does nothing """ pass @feature('pyext') @before_method('propagate_uselib_vars', 'apply_link') @after_method('apply_bundle') def init_pyext(self): """ Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the *lib* prefix from library names. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEXT' in self.uselib: self.uselib.append('PYEXT') # override shlib_PATTERN set by the osx module self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.macbundle_PATTERN = self.env.pyext_PATTERN self.env.fcshlib_PATTERN = self.env.dshlib_PATTERN = self.env.pyext_PATTERN try: if not self.install_path: return except AttributeError: self.install_path = '${PYTHONARCHDIR}' @feature('pyext') @before_method('apply_link', 'apply_bundle') def set_bundle(self): if Utils.unversioned_sys_platform() == 'darwin': self.mac_bundle = True @before_method('propagate_uselib_vars') @feature('pyembed') def init_pyembed(self): """ Add the PYEMBED variable. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEMBED' in self.uselib: self.uselib.append('PYEMBED') @conf def get_python_variables(self, variables, imports=None): """ Spawn a new python process to dump configuration variables :param variables: variables to print :type variables: list of string :param imports: one import by element :type imports: list of string :return: the variable values :rtype: list of string """ if not imports: try: imports = self.python_imports except AttributeError: imports = DISTUTILS_IMP program = list(imports) # copy program.append('') for v in variables: program.append("print(repr(%s))" % v) os_env = dict(os.environ) try: del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool except KeyError: pass try: out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env) except Errors.WafError: self.fatal('The distutils module is unusable: install "python-devel"?') self.to_log(out) return_values = [] for s in out.split('\n'): s = s.strip() if not s: continue if s == 'None': return_values.append(None) elif (s[0] == "'" and s[-1] == "'") or (s[0] == '"' and s[-1] == '"'): return_values.append(eval(s)) elif s[0].isdigit(): return_values.append(int(s)) else: break return return_values @conf def check_python_headers(conf): """ Check for headers and libraries necessary to extend or embed python by using the module *distutils*. On success the environment variables xxx_PYEXT and xxx_PYEMBED are added: * PYEXT: for compiling python extensions * PYEMBED: for embedding a python interpreter """ # FIXME rewrite env = conf.env if not env['CC_NAME'] and not env['CXX_NAME']: conf.fatal('load a compiler first (gcc, g++, ..)') if not env['PYTHON_VERSION']: conf.check_python_version() pybin = conf.env.PYTHON if not pybin: conf.fatal('Could not find the python executable') v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS'.split() try: lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) except RuntimeError: conf.fatal("Python development headers not found (-v for details).") vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)] conf.to_log("Configuration returned from %r:\n%r\n" % (pybin, '\n'.join(vals))) dct = dict(zip(v, lst)) x = 'MACOSX_DEPLOYMENT_TARGET' if dct[x]: conf.env[x] = conf.environ[x] = dct[x] env['pyext_PATTERN'] = '%s' + dct['SO'] # not a mistake # Check for python libraries for embedding all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEMBED') all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEXT') result = None #name = 'python' + env['PYTHON_VERSION'] # TODO simplify this for name in ('python' + env['PYTHON_VERSION'], 'python' + env['PYTHON_VERSION'] + 'm', 'python' + env['PYTHON_VERSION'].replace('.', '')): # LIBPATH_PYEMBED is already set; see if it works. if not result and env['LIBPATH_PYEMBED']: path = env['LIBPATH_PYEMBED'] conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) if not result and dct['LIBDIR']: path = [dct['LIBDIR']] conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) if not result and dct['LIBPL']: path = [dct['LIBPL']] conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) if not result: path = [os.path.join(dct['prefix'], "libs")] conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) if result: break # do not forget to set LIBPATH_PYEMBED if result: env['LIBPATH_PYEMBED'] = path env.append_value('LIB_PYEMBED', [name]) else: conf.to_log("\n\n### LIB NOT FOUND\n") # under certain conditions, python extensions must link to # python libraries, not just python embedding programs. if (Utils.is_win32 or sys.platform.startswith('os2') or dct['Py_ENABLE_SHARED']): env['LIBPATH_PYEXT'] = env['LIBPATH_PYEMBED'] env['LIB_PYEXT'] = env['LIB_PYEMBED'] # We check that pythonX.Y-config exists, and if it exists we # use it to get only the includes, else fall back to distutils. num = '.'.join(env['PYTHON_VERSION'].split('.')[:2]) conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', mandatory=False) includes = [] if conf.env.PYTHON_CONFIG: for incstr in conf.cmd_and_log([ conf.env.PYTHON_CONFIG, '--includes']).strip().split(): # strip the -I or /I if (incstr.startswith('-I') or incstr.startswith('/I')): incstr = incstr[2:] # append include path, unless already given if incstr not in includes: includes.append(incstr) conf.to_log("Include path for Python extensions (found via python-config --includes): %r\n" % (includes,)) env['INCLUDES_PYEXT'] = includes env['INCLUDES_PYEMBED'] = includes else: conf.to_log("Include path for Python extensions " "(found via distutils module): %r\n" % (dct['INCLUDEPY'],)) env['INCLUDES_PYEXT'] = [dct['INCLUDEPY']] env['INCLUDES_PYEMBED'] = [dct['INCLUDEPY']] # Code using the Python API needs to be compiled with -fno-strict-aliasing if env['CC_NAME'] == 'gcc': env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing']) if env['CXX_NAME'] == 'gcc': env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CC_NAME == "msvc": from distutils.msvccompiler import MSVCCompiler dist_compiler = MSVCCompiler() dist_compiler.initialize() env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared) # See if it compiles try: conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg=':-(') except conf.errors.ConfigurationError: # python3.2, oh yeah xx = conf.env.CXX_NAME and 'cxx' or 'c' flags = ['--cflags', '--libs', '--ldflags'] for f in flags: conf.check_cfg(msg='Asking python-config for pyembed %s flags' % f, path=conf.env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=[f]) conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', msg='Getting pyembed flags from python-config', fragment=FRAG, errmsg='Could not build a python embedded interpreter', features='%s %sprogram pyembed' % (xx, xx)) for f in flags: conf.check_cfg(msg='Asking python-config for pyext %s flags' % f, path=conf.env.PYTHON_CONFIG, package='', uselib_store='PYEXT', args=[f]) conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', msg='Getting pyext flags from python-config', features='%s %sshlib pyext' % (xx, xx), fragment=FRAG, errmsg='Could not build python extensions') @conf def check_python_version(conf, minver=None): """ Check if the python interpreter is found matching a given minimum version. minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' (eg. '2.4') of the actual python version found, and PYTHONDIR is defined, pointing to the site-packages directory appropriate for this python version, where modules/packages/extensions should be installed. :param minver: minimum version :type minver: tuple of int """ assert minver is None or isinstance(minver, tuple) pybin = conf.env['PYTHON'] if not pybin: conf.fatal('could not find the python executable') # Get python version string cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))'] Logs.debug('python: Running python command %r' % cmd) lines = conf.cmd_and_log(cmd).split() assert len(lines) == 5, "found %i lines, expected 5: %r" % (len(lines), lines) pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) # compare python version with the minimum required result = (minver is None) or (pyver_tuple >= minver) if result: # define useful environment variables pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) conf.env['PYTHON_VERSION'] = pyver if 'PYTHONDIR' in conf.environ: pydir = conf.environ['PYTHONDIR'] else: if Utils.is_win32: (python_LIBDEST, pydir) = conf.get_python_variables( ["get_config_var('LIBDEST') or ''", "get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) else: python_LIBDEST = None (pydir,) = conf.get_python_variables( ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) if python_LIBDEST is None: if conf.env['LIBDIR']: python_LIBDEST = os.path.join(conf.env['LIBDIR'], "python" + pyver) else: python_LIBDEST = os.path.join(conf.env['PREFIX'], "lib", "python" + pyver) if 'PYTHONARCHDIR' in conf.environ: pyarchdir = conf.environ['PYTHONARCHDIR'] else: (pyarchdir, ) = conf.get_python_variables( ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) if not pyarchdir: pyarchdir = pydir if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist conf.define('PYTHONDIR', pydir) conf.define('PYTHONARCHDIR', pyarchdir) conf.env['PYTHONDIR'] = pydir conf.env['PYTHONARCHDIR'] = pyarchdir # Feedback pyver_full = '.'.join(map(str, pyver_tuple[:3])) if minver is None: conf.msg('Checking for python version', pyver_full) else: minver_str = '.'.join(map(str, minver)) conf.msg('Checking for python version', pyver_tuple, ">= %s" % (minver_str,) and 'GREEN' or 'YELLOW') if not result: conf.fatal('The python version is too old, expecting %r' % (minver,)) PYTHON_MODULE_TEMPLATE = ''' import %s as current_module version = getattr(current_module, '__version__', None) if version is not None: print(str(version)) else: print('unknown version') ''' @conf def check_python_module(conf, module_name, condition=''): """ Check if the selected python interpreter can import the given python module:: def configure(conf): conf.check_python_module('pygccxml') conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)") :param module_name: module :type module_name: string """ msg = 'Python module %s' % module_name if condition: msg = '%s (%s)' % (msg, condition) conf.start_msg(msg) try: ret = conf.cmd_and_log(conf.env['PYTHON'] + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) except Exception: conf.end_msg(False) conf.fatal('Could not find the python module %r' % module_name) ret = ret.strip() if condition: conf.end_msg(ret) if ret == 'unknown version': conf.fatal('Could not check the %s version' % module_name) from distutils.version import LooseVersion def num(*k): if isinstance(k[0], int): return LooseVersion('.'.join([str(x) for x in k])) else: return LooseVersion(k[0]) d = {'num': num, 'ver': LooseVersion(ret)} ev = eval(condition, {}, d) if not ev: conf.fatal('The %s version does not satisfy the requirements' % module_name) else: if ret == 'unknown version': conf.end_msg(True) else: conf.end_msg(ret) def configure(conf): """ Detect the python interpreter """ try: conf.find_program('python', var='PYTHON') except conf.errors.ConfigurationError: Logs.warn("could not find a python executable, setting to sys.executable '%s'" % sys.executable) conf.env.PYTHON = sys.executable if conf.env.PYTHON != sys.executable: Logs.warn("python executable %r differs from system %r" % (conf.env.PYTHON, sys.executable)) conf.env.PYTHON = conf.cmd_to_list(conf.env.PYTHON) v = conf.env v['PYCMD'] = '"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"' v['PYFLAGS'] = '' v['PYFLAGS_OPT'] = '-O' v['PYC'] = getattr(Options.options, 'pyc', 1) v['PYO'] = getattr(Options.options, 'pyo', 1) def options(opt): """ Add the options ``--nopyc`` and ``--nopyo`` """ opt.add_option('--nopyc', action='store_false', default=1, help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]', dest = 'pyc') opt.add_option('--nopyo', action='store_false', default=1, help='Do not install optimised compiled .pyo files (configuration) [Default:install]', dest='pyo') debian/waf-1.7/waflib/Tools/c.py0000664000000000000000000000263012145745420013415 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) "Base for c programs/libraries" from waflib import TaskGen, Task, Utils from waflib.Tools import c_preproc from waflib.Tools.ccroot import link_task, stlink_task @TaskGen.extension('.c') def c_hook(self, node): "Bind the c file extension to the creation of a :py:class:`waflib.Tools.c.c` instance" return self.create_compiled_task('c', node) class c(Task.Task): "Compile C files into object files" run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT}' vars = ['CCDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan class cprogram(link_task): "Link object files into a c program" run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' ext_out = ['.bin'] vars = ['LINKDEPS'] inst_to = '${BINDIR}' class cshlib(cprogram): "Link object files into a c shared library" inst_to = '${LIBDIR}' class cstlib(stlink_task): "Link object files into a c static library" pass # do not remove debian/waf-1.7/waflib/Tools/gnu_dirs.py0000664000000000000000000001205012145745420015002 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ Sets various standard variables such as INCLUDEDIR. SBINDIR and others. To use this module just call:: opt.load('gnu_dirs') and:: conf.load('gnu_dirs') Add options for the standard GNU directories, this tool will add the options found in autotools, and will update the environment with the following installation variables: ============== ========================================= ======================= Variable Description Value ============== ========================================= ======================= PREFIX architecture-independent files /usr/local EXEC_PREFIX architecture-dependent files PREFIX BINDIR user executables EXEC_PREFIX/bin SBINDIR user executables EXEC_PREFIX/sbin LIBEXECDIR program executables EXEC_PREFIX/libexec SYSCONFDIR read-only single-machine data PREFIX/etc SHAREDSTATEDIR modifiable architecture-independent data PREFIX/com LOCALSTATEDIR modifiable single-machine data PREFIX/var LIBDIR object code libraries EXEC_PREFIX/lib INCLUDEDIR C header files PREFIX/include OLDINCLUDEDIR C header files for non-gcc /usr/include DATAROOTDIR read-only arch.-independent data root PREFIX/share DATADIR read-only architecture-independent data DATAROOTDIR INFODIR info documentation DATAROOTDIR/info LOCALEDIR locale-dependent data DATAROOTDIR/locale MANDIR man documentation DATAROOTDIR/man DOCDIR documentation root DATAROOTDIR/doc/APPNAME HTMLDIR html documentation DOCDIR DVIDIR dvi documentation DOCDIR PDFDIR pdf documentation DOCDIR PSDIR ps documentation DOCDIR ============== ========================================= ======================= """ import os from waflib import Utils, Options, Context _options = [x.split(', ') for x in ''' bindir, user executables, ${EXEC_PREFIX}/bin sbindir, system admin executables, ${EXEC_PREFIX}/sbin libexecdir, program executables, ${EXEC_PREFIX}/libexec sysconfdir, read-only single-machine data, ${PREFIX}/etc sharedstatedir, modifiable architecture-independent data, ${PREFIX}/com localstatedir, modifiable single-machine data, ${PREFIX}/var libdir, object code libraries, ${EXEC_PREFIX}/lib includedir, C header files, ${PREFIX}/include oldincludedir, C header files for non-gcc, /usr/include datarootdir, read-only arch.-independent data root, ${PREFIX}/share datadir, read-only architecture-independent data, ${DATAROOTDIR} infodir, info documentation, ${DATAROOTDIR}/info localedir, locale-dependent data, ${DATAROOTDIR}/locale mandir, man documentation, ${DATAROOTDIR}/man docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} htmldir, html documentation, ${DOCDIR} dvidir, dvi documentation, ${DOCDIR} pdfdir, pdf documentation, ${DOCDIR} psdir, ps documentation, ${DOCDIR} '''.split('\n') if x] def configure(conf): """ Read the command-line options to set lots of variables in *conf.env*. The variables BINDIR and LIBDIR will be overwritten. """ def get_param(varname, default): return getattr(Options.options, varname, '') or default env = conf.env env.LIBDIR = env.BINDIR = [] env.EXEC_PREFIX = get_param('EXEC_PREFIX', env.PREFIX) env.PACKAGE = getattr(Context.g_module, 'APPNAME', None) or env.PACKAGE complete = False iter = 0 while not complete and iter < len(_options) + 1: iter += 1 complete = True for name, help, default in _options: name = name.upper() if not env[name]: try: env[name] = Utils.subst_vars(get_param(name, default).replace('/', os.sep), env) except TypeError: complete = False if not complete: lst = [name for name, _, _ in _options if not env[name.upper()]] raise conf.errors.WafError('Variable substitution failure %r' % lst) def options(opt): """ Add lots of command-line options, for example:: --exec-prefix: EXEC_PREFIX """ inst_dir = opt.add_option_group('Installation directories', 'By default, "waf install" will put the files in\ "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') for k in ('--prefix', '--destdir'): option = opt.parser.get_option(k) if option: opt.parser.remove_option(k) inst_dir.add_option(option) inst_dir.add_option('--exec-prefix', help = 'installation prefix [Default: ${PREFIX}]', default = '', dest = 'EXEC_PREFIX') dirs_options = opt.add_option_group('Pre-defined installation directories', '') for name, help, default in _options: option_name = '--' + name str_default = default str_help = '%s [Default: %s]' % (help, str_default) dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) debian/waf-1.7/waflib/Tools/waf_unit_test.py0000664000000000000000000001366612145745420016061 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 # Thomas Nagy, 2010 """ Unit testing system for C/C++/D providing test execution: * in parallel, by using ``waf -j`` * partial (only the tests that have changed) or full (by using ``waf --alltests``) The tests are declared by adding the **test** feature to programs:: def options(opt): opt.load('compiler_cxx waf_unit_test') def configure(conf): conf.load('compiler_cxx waf_unit_test') def build(bld): bld(features='cxx cxxprogram test', source='main.cpp', target='app') # or bld.program(features='test', source='main2.cpp', target='app2') When the build is executed, the program 'test' will be built and executed without arguments. The success/failure is detected by looking at the return code. The status and the standard output/error are stored on the build context. The results can be displayed by registering a callback function. Here is how to call the predefined callback:: def build(bld): bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.summary) """ import os, sys from waflib.TaskGen import feature, after_method from waflib import Utils, Task, Logs, Options testlock = Utils.threading.Lock() @feature('test') @after_method('apply_link') def make_test(self): """Create the unit test task. There can be only one unit test task by task generator.""" if getattr(self, 'link_task', None): self.create_task('utest', self.link_task.outputs) class utest(Task.Task): """ Execute a unit test """ color = 'PINK' after = ['vnum', 'inst'] vars = [] def runnable_status(self): """ Always execute the task if `waf --alltests` was used or no tests if ``waf --notests`` was used """ if getattr(Options.options, 'no_tests', False): return Task.SKIP_ME ret = super(utest, self).runnable_status() if ret == Task.SKIP_ME: if getattr(Options.options, 'all_tests', False): return Task.RUN_ME return ret def run(self): """ Execute the test. The execution is always successful, but the results are stored on ``self.generator.bld.utest_results`` for postprocessing. """ filename = self.inputs[0].abspath() self.ut_exec = getattr(self.generator, 'ut_exec', [filename]) if getattr(self.generator, 'ut_fun', None): self.generator.ut_fun(self) try: fu = getattr(self.generator.bld, 'all_test_paths') except AttributeError: fu = os.environ.copy() lst = [] for g in self.generator.bld.groups: for tg in g: if getattr(tg, 'link_task', None): lst.append(tg.link_task.outputs[0].parent.abspath()) def add_path(dct, path, var): dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) if Utils.is_win32: add_path(fu, lst, 'PATH') elif Utils.unversioned_sys_platform() == 'darwin': add_path(fu, lst, 'DYLD_LIBRARY_PATH') add_path(fu, lst, 'LD_LIBRARY_PATH') else: add_path(fu, lst, 'LD_LIBRARY_PATH') self.generator.bld.all_test_paths = fu cwd = getattr(self.generator, 'ut_cwd', '') or self.inputs[0].parent.abspath() testcmd = getattr(Options.options, 'testcmd', False) if testcmd: self.ut_exec = (testcmd % self.ut_exec[0]).split(' ') proc = Utils.subprocess.Popen(self.ut_exec, cwd=cwd, env=fu, stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE) (stdout, stderr) = proc.communicate() tup = (filename, proc.returncode, stdout, stderr) self.generator.utest_result = tup testlock.acquire() try: bld = self.generator.bld Logs.debug("ut: %r", tup) try: bld.utest_results.append(tup) except AttributeError: bld.utest_results = [tup] finally: testlock.release() def summary(bld): """ Display an execution summary:: def build(bld): bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.summary) """ lst = getattr(bld, 'utest_results', []) if lst: Logs.pprint('CYAN', 'execution summary') total = len(lst) tfail = len([x for x in lst if x[1]]) Logs.pprint('CYAN', ' tests that pass %d/%d' % (total-tfail, total)) for (f, code, out, err) in lst: if not code: Logs.pprint('CYAN', ' %s' % f) Logs.pprint('CYAN', ' tests that fail %d/%d' % (tfail, total)) for (f, code, out, err) in lst: if code: Logs.pprint('CYAN', ' %s' % f) def set_exit_code(bld): """ If any of the tests fail waf will exit with that exit code. This is useful if you have an automated build system which need to report on errors from the tests. You may use it like this: def build(bld): bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.set_exit_code) """ lst = getattr(bld, 'utest_results', []) for (f, code, out, err) in lst: if code: msg = [] if out: msg.append('stdout:%s%s' % (os.linesep, out.decode('utf-8'))) if err: msg.append('stderr:%s%s' % (os.linesep, err.decode('utf-8'))) bld.fatal(os.linesep.join(msg)) def options(opt): """ Provide the ``--alltests``, ``--notests`` and ``--testcmd`` command-line options. """ opt.add_option('--notests', action='store_true', default=False, help='Exec no unit tests', dest='no_tests') opt.add_option('--alltests', action='store_true', default=False, help='Exec all unit tests', dest='all_tests') opt.add_option('--testcmd', action='store', default=False, help = 'Run the unit tests using the test-cmd string' ' example "--test-cmd="valgrind --error-exitcode=1' ' %s" to run under valgrind', dest='testcmd') debian/waf-1.7/waflib/Tools/fc.py0000664000000000000000000001453312145745420013570 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) """ fortran support """ import re from waflib import Utils, Task, TaskGen, Logs from waflib.Tools import ccroot, fc_config, fc_scan from waflib.TaskGen import feature, before_method, after_method, extension from waflib.Configure import conf ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES']) ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) @feature('fcprogram', 'fcshlib', 'fcstlib', 'fcprogram_test') def dummy(self): pass @extension('.f', '.f90', '.F', '.F90', '.for', '.FOR') def fc_hook(self, node): "Bind the typical Fortran file extensions to the creation of a :py:class:`waflib.Tools.fc.fc` instance" return self.create_compiled_task('fc', node) @conf def modfile(conf, name): """ Turn a module name into the right module file name. Defaults to all lower case. """ return {'lower' :name.lower() + '.mod', 'lower.MOD' :name.upper() + '.MOD', 'UPPER.mod' :name.upper() + '.mod', 'UPPER' :name.upper() + '.MOD'}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] def get_fortran_tasks(tsk): """ Obtain all other fortran tasks from the same build group. Those tasks must not have the attribute 'nomod' or 'mod_fortran_done' """ bld = tsk.generator.bld tasks = bld.get_tasks_group(bld.get_group_idx(tsk.generator)) return [x for x in tasks if isinstance(x, fc) and not getattr(x, 'nomod', None) and not getattr(x, 'mod_fortran_done', None)] class fc(Task.Task): """ The fortran tasks can only run when all fortran tasks in the current group are ready to be executed This may cause a deadlock if another fortran task is waiting for something that cannot happen (circular dependency) in this case, set the 'nomod=True' on those tasks instances to break the loop """ color = 'GREEN' run_str = '${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()}' vars = ["FORTRANMODPATHFLAG"] def scan(self): """scanner for fortran dependencies""" tmp = fc_scan.fortran_parser(self.generator.includes_nodes) tmp.task = self tmp.start(self.inputs[0]) if Logs.verbose: Logs.debug('deps: deps for %r: %r; unresolved %r' % (self.inputs, tmp.nodes, tmp.names)) return (tmp.nodes, tmp.names) def runnable_status(self): """ Set the mod file outputs and the dependencies on the mod files over all the fortran tasks executed by the main thread so there are no concurrency issues """ if getattr(self, 'mod_fortran_done', None): return super(fc, self).runnable_status() # now, if we reach this part it is because this fortran task is the first in the list bld = self.generator.bld # obtain the fortran tasks lst = get_fortran_tasks(self) # disable this method for other tasks for tsk in lst: tsk.mod_fortran_done = True # wait for all the .f tasks to be ready for execution # and ensure that the scanners are called at least once for tsk in lst: ret = tsk.runnable_status() if ret == Task.ASK_LATER: # we have to wait for one of the other fortran tasks to be ready # this may deadlock if there are dependencies between the fortran tasks # but this should not happen (we are setting them here!) for x in lst: x.mod_fortran_done = None # TODO sort the list of tasks in bld.producer.outstanding to put all fortran tasks at the end return Task.ASK_LATER ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) # the .mod files to create for tsk in lst: key = tsk.uid() for x in bld.raw_deps[key]: if x.startswith('MOD@'): name = bld.modfile(x.replace('MOD@', '')) node = bld.srcnode.find_or_declare(name) tsk.set_outputs(node) outs[id(node)].add(tsk) # the .mod files to use for tsk in lst: key = tsk.uid() for x in bld.raw_deps[key]: if x.startswith('USE@'): name = bld.modfile(x.replace('USE@', '')) node = bld.srcnode.find_resource(name) if node and node not in tsk.outputs: if not node in bld.node_deps[key]: bld.node_deps[key].append(node) ins[id(node)].add(tsk) # if the intersection matches, set the order for k in ins.keys(): for a in ins[k]: a.run_after.update(outs[k]) # the scanner cannot output nodes, so we have to set them # ourselves as task.dep_nodes (additional input nodes) tmp = [] for t in outs[k]: tmp.extend(t.outputs) a.dep_nodes.extend(tmp) a.dep_nodes.sort(key=lambda x: x.abspath()) # the task objects have changed: clear the signature cache for tsk in lst: try: delattr(tsk, 'cache_sig') except AttributeError: pass return super(fc, self).runnable_status() class fcprogram(ccroot.link_task): """Link fortran programs""" color = 'YELLOW' run_str = '${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB}' inst_to = '${BINDIR}' class fcshlib(fcprogram): """Link fortran libraries""" inst_to = '${LIBDIR}' class fcprogram_test(fcprogram): """Custom link task to obtain the compiler outputs for fortran configuration tests""" def can_retrieve_cache(self): """This task is always executed""" return False def runnable_status(self): """This task is always executed""" ret = super(fcprogram_test, self).runnable_status() if ret == Task.SKIP_ME: ret = Task.RUN_ME return ret def exec_command(self, cmd, **kw): """Store the compiler std our/err onto the build context, to bld.out + bld.err""" bld = self.generator.bld kw['shell'] = isinstance(cmd, str) kw['stdout'] = kw['stderr'] = Utils.subprocess.PIPE kw['cwd'] = bld.variant_dir bld.out = bld.err = '' bld.to_log('command: %s\n' % cmd) kw['output'] = 0 try: (bld.out, bld.err) = bld.cmd_and_log(cmd, **kw) except Exception as e: return -1 if bld.out: bld.to_log("out: %s\n" % bld.out) if bld.err: bld.to_log("err: %s\n" % bld.err) class fcstlib(ccroot.stlink_task): """Link fortran static libraries (uses ar by default)""" pass # do not remove the pass statement debian/waf-1.7/waflib/Tools/nasm.py0000664000000000000000000000104212145745420014125 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Nasm tool (asm processing) """ import waflib.Tools.asm # leave this from waflib.TaskGen import feature @feature('asm') def apply_nasm_vars(self): """provided for compatibility""" self.env.append_value('ASFLAGS', self.to_list(getattr(self, 'nasm_flags', []))) def configure(conf): """ Detect nasm/yasm and set the variable *AS* """ nasm = conf.find_program(['nasm', 'yasm'], var='AS') conf.env.AS_TGT_F = ['-o'] conf.env.ASLNK_TGT_F = ['-o'] conf.load('asm') debian/waf-1.7/waflib/Tools/cxx.py0000664000000000000000000000311712145745420013776 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "Base for c++ programs and libraries" from waflib import TaskGen, Task, Utils from waflib.Tools import c_preproc from waflib.Tools.ccroot import link_task, stlink_task @TaskGen.extension('.cpp','.cc','.cxx','.C','.c++') def cxx_hook(self, node): "Bind the c++ file extensions to the creation of a :py:class:`waflib.Tools.cxx.cxx` instance" return self.create_compiled_task('cxx', node) if not '.c' in TaskGen.task_gen.mappings: TaskGen.task_gen.mappings['.c'] = TaskGen.task_gen.mappings['.cpp'] class cxx(Task.Task): "Compile C++ files into object files" run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}' vars = ['CXXDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan class cxxprogram(link_task): "Link object files into a c++ program" run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' vars = ['LINKDEPS'] ext_out = ['.bin'] inst_to = '${BINDIR}' class cxxshlib(cxxprogram): "Link object files into a c++ shared library" inst_to = '${LIBDIR}' class cxxstlib(stlink_task): "Link object files into a c++ static library" pass # do not remove debian/waf-1.7/waflib/Tools/fc_config.py0000664000000000000000000003242412145745420015114 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) """ Fortran configuration helpers """ import re, shutil, os, sys, string, shlex from waflib.Configure import conf from waflib.TaskGen import feature, after_method, before_method from waflib import Build, Utils FC_FRAGMENT = ' program main\n end program main\n' FC_FRAGMENT2 = ' PROGRAM MAIN\n END\n' # what's the actual difference between these? @conf def fc_flags(conf): """ Define common fortran configuration flags and file extensions """ v = conf.env v['FC_SRC_F'] = [] v['FC_TGT_F'] = ['-c', '-o'] v['FCINCPATH_ST'] = '-I%s' v['FCDEFINES_ST'] = '-D%s' if not v['LINK_FC']: v['LINK_FC'] = v['FC'] v['FCLNK_SRC_F'] = [] v['FCLNK_TGT_F'] = ['-o'] v['FCFLAGS_fcshlib'] = ['-fpic'] v['LINKFLAGS_fcshlib'] = ['-shared'] v['fcshlib_PATTERN'] = 'lib%s.so' v['fcstlib_PATTERN'] = 'lib%s.a' v['FCLIB_ST'] = '-l%s' v['FCLIBPATH_ST'] = '-L%s' v['FCSTLIB_ST'] = '-l%s' v['FCSTLIBPATH_ST'] = '-L%s' v['FCSTLIB_MARKER'] = '-Wl,-Bstatic' v['FCSHLIB_MARKER'] = '-Wl,-Bdynamic' v['SONAME_ST'] = '-Wl,-h,%s' @conf def fc_add_flags(conf): """ FCFLAGS? """ conf.add_os_flags('FCFLAGS') conf.add_os_flags('LDFLAGS', 'LINKFLAGS') @conf def check_fortran(self, *k, **kw): """See if the fortran compiler works by compiling a simple fortran program""" self.check_cc( fragment = FC_FRAGMENT, compile_filename = 'test.f', features = 'fc fcprogram', msg = 'Compiling a simple fortran app') @conf def check_fc(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *Fortran* programming language (Overriding the C defaults in :py:func:`waflib.Tools.c_config.validate_c` here) """ kw['compiler'] = 'fc' if not 'compile_mode' in kw: kw['compile_mode'] = 'fc' if not 'type' in kw: kw['type'] = 'fcprogram' if not 'compile_filename' in kw: kw['compile_filename'] = 'test.f90' if not 'code' in kw: kw['code'] = FC_FRAGMENT return self.check(*k, **kw) # ------------------------------------------------------------------------ # --- These are the default platform modifiers, refactored here for # convenience. gfortran and g95 have much overlap. # ------------------------------------------------------------------------ @conf def fortran_modifier_darwin(conf): """ Define fortran flags and extensions for the OSX systems """ v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_fcshlib'] = ['-dynamiclib'] v['fcshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = '-framework %s' v['LINKFLAGS_fcstlib'] = [] v['FCSHLIB_MARKER'] = '' v['FCSTLIB_MARKER'] = '' v['SONAME_ST'] = '' @conf def fortran_modifier_win32(conf): """Define fortran flags for the windows platforms""" v = conf.env v['fcprogram_PATTERN'] = v['fcprogram_test_PATTERN'] = '%s.exe' v['fcshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['FCFLAGS_fcshlib'] = [] v.append_value('FCFLAGS_fcshlib', ['-DDLL_EXPORT']) # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def fortran_modifier_cygwin(conf): """Define fortran flags for use on cygwin""" fortran_modifier_win32(conf) v = conf.env v['fcshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_fcshlib', ['-Wl,--enable-auto-image-base']) v['FCFLAGS_fcshlib'] = [] # ------------------------------------------------------------------------ @conf def check_fortran_dummy_main(self, *k, **kw): """ Guess if a main function is needed by compiling a code snippet with the C compiler and link with the Fortran compiler TODO: (DC) - handling dialects (F77, F90, etc... -> needs core support first) - fix dummy main check (AC_FC_DUMMY_MAIN vs AC_FC_MAIN) TODO: what does the above mean? (ita) """ if not self.env.CC: self.fatal('A c compiler is required for check_fortran_dummy_main') lst = ['MAIN__', '__MAIN', '_MAIN', 'MAIN_', 'MAIN'] lst.extend([m.lower() for m in lst]) lst.append('') self.start_msg('Detecting whether we need a dummy main') for main in lst: kw['fortran_main'] = main try: self.check_cc( fragment = 'int %s() { return 0; }\n' % (main or 'test'), features = 'c fcprogram', mandatory = True ) if not main: self.env.FC_MAIN = -1 self.end_msg('no') else: self.env.FC_MAIN = main self.end_msg('yes %s' % main) break except self.errors.ConfigurationError: pass else: self.end_msg('not found') self.fatal('could not detect whether fortran requires a dummy main, see the config.log') # ------------------------------------------------------------------------ GCC_DRIVER_LINE = re.compile('^Driving:') POSIX_STATIC_EXT = re.compile('\S+\.a') POSIX_LIB_FLAGS = re.compile('-l\S+') @conf def is_link_verbose(self, txt): """Return True if 'useful' link options can be found in txt""" assert isinstance(txt, str) for line in txt.splitlines(): if not GCC_DRIVER_LINE.search(line): if POSIX_STATIC_EXT.search(line) or POSIX_LIB_FLAGS.search(line): return True return False @conf def check_fortran_verbose_flag(self, *k, **kw): """ Check what kind of verbose (-v) flag works, then set it to env.FC_VERBOSE_FLAG """ self.start_msg('fortran link verbose flag') for x in ['-v', '--verbose', '-verbose', '-V']: try: self.check_cc( features = 'fc fcprogram_test', fragment = FC_FRAGMENT2, compile_filename = 'test.f', linkflags = [x], mandatory=True ) except self.errors.ConfigurationError: pass else: # output is on stderr or stdout (for xlf) if self.is_link_verbose(self.test_bld.err) or self.is_link_verbose(self.test_bld.out): self.end_msg(x) break else: self.end_msg('failure') self.fatal('Could not obtain the fortran link verbose flag (see config.log)') self.env.FC_VERBOSE_FLAG = x return x # ------------------------------------------------------------------------ # linkflags which match those are ignored LINKFLAGS_IGNORED = [r'-lang*', r'-lcrt[a-zA-Z0-9\.]*\.o', r'-lc$', r'-lSystem', r'-libmil', r'-LIST:*', r'-LNO:*'] if os.name == 'nt': LINKFLAGS_IGNORED.extend([r'-lfrt*', r'-luser32', r'-lkernel32', r'-ladvapi32', r'-lmsvcrt', r'-lshell32', r'-lmingw', r'-lmoldname']) else: LINKFLAGS_IGNORED.append(r'-lgcc*') RLINKFLAGS_IGNORED = [re.compile(f) for f in LINKFLAGS_IGNORED] def _match_ignore(line): """Returns True if the line should be ignored (fortran test for verbosity).""" for i in RLINKFLAGS_IGNORED: if i.match(line): return True return False def parse_fortran_link(lines): """Given the output of verbose link of Fortran compiler, this returns a list of flags necessary for linking using the standard linker.""" # TODO: On windows ? final_flags = [] for line in lines: if not GCC_DRIVER_LINE.match(line): _parse_flink_line(line, final_flags) return final_flags SPACE_OPTS = re.compile('^-[LRuYz]$') NOSPACE_OPTS = re.compile('^-[RL]') def _parse_flink_line(line, final_flags): """private""" lexer = shlex.shlex(line, posix = True) lexer.whitespace_split = True t = lexer.get_token() tmp_flags = [] while t: def parse(token): # Here we go (convention for wildcard is shell, not regex !) # 1 TODO: we first get some root .a libraries # 2 TODO: take everything starting by -bI:* # 3 Ignore the following flags: -lang* | -lcrt*.o | -lc | # -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*) # 4 take into account -lkernel32 # 5 For options of the kind -[[LRuYz]], as they take one argument # after, the actual option is the next token # 6 For -YP,*: take and replace by -Larg where arg is the old # argument # 7 For -[lLR]*: take # step 3 if _match_ignore(token): pass # step 4 elif token.startswith('-lkernel32') and sys.platform == 'cygwin': tmp_flags.append(token) # step 5 elif SPACE_OPTS.match(token): t = lexer.get_token() if t.startswith('P,'): t = t[2:] for opt in t.split(os.pathsep): tmp_flags.append('-L%s' % opt) # step 6 elif NOSPACE_OPTS.match(token): tmp_flags.append(token) # step 7 elif POSIX_LIB_FLAGS.match(token): tmp_flags.append(token) else: # ignore anything not explicitely taken into account pass t = lexer.get_token() return t t = parse(t) final_flags.extend(tmp_flags) return final_flags @conf def check_fortran_clib(self, autoadd=True, *k, **kw): """ Obtain the flags for linking with the C library if this check works, add uselib='CLIB' to your task generators """ if not self.env.FC_VERBOSE_FLAG: self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') self.start_msg('Getting fortran runtime link flags') try: self.check_cc( fragment = FC_FRAGMENT2, compile_filename = 'test.f', features = 'fc fcprogram_test', linkflags = [self.env.FC_VERBOSE_FLAG] ) except Exception: self.end_msg(False) if kw.get('mandatory', True): conf.fatal('Could not find the c library flags') else: out = self.test_bld.err flags = parse_fortran_link(out.splitlines()) self.end_msg('ok (%s)' % ' '.join(flags)) self.env.LINKFLAGS_CLIB = flags return flags return [] def getoutput(conf, cmd, stdin=False): """ TODO a bit redundant, can be removed anytime """ if stdin: stdin = Utils.subprocess.PIPE else: stdin = None env = conf.env.env or None try: p = Utils.subprocess.Popen(cmd, stdin=stdin, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env) if stdin: p.stdin.write('\n'.encode()) out, err = p.communicate() except Exception: conf.fatal('could not determine the compiler version %r' % cmd) if not isinstance(out, str): out = out.decode(sys.stdout.encoding or 'iso8859-1') if not isinstance(err, str): err = err.decode(sys.stdout.encoding or 'iso8859-1') return (out, err) # ------------------------------------------------------------------------ ROUTINES_CODE = """\ subroutine foobar() return end subroutine foo_bar() return end """ MAIN_CODE = """ void %(dummy_func_nounder)s(void); void %(dummy_func_under)s(void); int %(main_func_name)s() { %(dummy_func_nounder)s(); %(dummy_func_under)s(); return 0; } """ @feature('link_main_routines_func') @before_method('process_source') def link_main_routines_tg_method(self): """ The configuration test declares a unique task generator, so we create other task generators from there for fortran link tests """ def write_test_file(task): task.outputs[0].write(task.generator.code) bld = self.bld bld(rule=write_test_file, target='main.c', code=MAIN_CODE % self.__dict__) bld(rule=write_test_file, target='test.f', code=ROUTINES_CODE) bld(features='fc fcstlib', source='test.f', target='test') bld(features='c fcprogram', source='main.c', target='app', use='test') def mangling_schemes(): """ Generate triplets for use with mangle_name (used in check_fortran_mangling) the order is tuned for gfortan """ for u in ['_', '']: for du in ['', '_']: for c in ["lower", "upper"]: yield (u, du, c) def mangle_name(u, du, c, name): """Mangle a name from a triplet (used in check_fortran_mangling)""" return getattr(name, c)() + u + (name.find('_') != -1 and du or '') @conf def check_fortran_mangling(self, *k, **kw): """ Detect the mangling scheme, sets FORTRAN_MANGLING to the triplet found This test will compile a fortran static library, then link a c app against it """ if not self.env.CC: self.fatal('A c compiler is required for link_main_routines') if not self.env.FC: self.fatal('A fortran compiler is required for link_main_routines') if not self.env.FC_MAIN: self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') self.start_msg('Getting fortran mangling scheme') for (u, du, c) in mangling_schemes(): try: self.check_cc( compile_filename = [], features = 'link_main_routines_func', msg = 'nomsg', errmsg = 'nomsg', mandatory=True, dummy_func_nounder = mangle_name(u, du, c, "foobar"), dummy_func_under = mangle_name(u, du, c, "foo_bar"), main_func_name = self.env.FC_MAIN ) except self.errors.ConfigurationError: pass else: self.end_msg("ok ('%s', '%s', '%s-case')" % (u, du, c)) self.env.FORTRAN_MANGLING = (u, du, c) break else: self.end_msg(False) self.fatal('mangler not found') return (u, du, c) @feature('pyext') @before_method('propagate_uselib_vars', 'apply_link') def set_lib_pat(self): """Set the fortran flags for linking with the python library""" self.env['fcshlib_PATTERN'] = self.env['pyext_PATTERN'] @conf def detect_openmp(self): for x in ['-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp']: try: self.check_fc( msg='Checking for OpenMP flag %s' % x, fragment='program main\n call omp_get_num_threads()\nend program main', fcflags=x, linkflags=x, uselib_store='OPENMP' ) except self.errors.ConfigurationError: pass else: break else: self.fatal('Could not find OpenMP') debian/waf-1.7/waflib/Tools/cs.py0000664000000000000000000001503112145745420013577 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ C# support. A simple example:: def configure(conf): conf.load('cs') def build(bld): bld(features='cs', source='main.cs', gen='foo') Note that the configuration may compile C# snippets:: FRAG = ''' namespace Moo { public class Test { public static int Main(string[] args) { return 0; } } }''' def configure(conf): conf.check(features='cs', fragment=FRAG, compile_filename='test.cs', gen='test.exe', bintype='exe', csflags=['-pkg:gtk-sharp-2.0'], msg='Checking for Gtksharp support') """ from waflib import Utils, Task, Options, Logs, Errors from waflib.TaskGen import before_method, after_method, feature from waflib.Tools import ccroot from waflib.Configure import conf import os, tempfile ccroot.USELIB_VARS['cs'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) ccroot.lib_patterns['csshlib'] = ['%s'] @feature('cs') @before_method('process_source') def apply_cs(self): """ Create a C# task bound to the attribute *cs_task*. There can be only one C# task by task generator. """ cs_nodes = [] no_nodes = [] for x in self.to_nodes(self.source): if x.name.endswith('.cs'): cs_nodes.append(x) else: no_nodes.append(x) self.source = no_nodes bintype = getattr(self, 'bintype', self.gen.endswith('.dll') and 'library' or 'exe') self.cs_task = tsk = self.create_task('mcs', cs_nodes, self.path.find_or_declare(self.gen)) tsk.env.CSTYPE = '/target:%s' % bintype tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() self.env.append_value('CSFLAGS', '/platform:%s' % getattr(self, 'platform', 'anycpu')) inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') if inst_to: # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) self.install_task = self.bld.install_files(inst_to, self.cs_task.outputs[:], env=self.env, chmod=mod) @feature('cs') @after_method('apply_cs') def use_cs(self): """ C# applications honor the **use** keyword:: def build(bld): bld(features='cs', source='My.cs', bintype='library', gen='my.dll', name='mylib') bld(features='cs', source='Hi.cs', includes='.', bintype='exe', gen='hi.exe', use='mylib', name='hi') """ names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except Errors.WafError: self.env.append_value('CSFLAGS', '/reference:%s' % x) continue y.post() tsk = getattr(y, 'cs_task', None) or getattr(y, 'link_task', None) if not tsk: self.bld.fatal('cs task has no link task for use %r' % self) self.cs_task.dep_nodes.extend(tsk.outputs) # dependency self.cs_task.set_run_after(tsk) # order (redundant, the order is infered from the nodes inputs/outputs) self.env.append_value('CSFLAGS', '/reference:%s' % tsk.outputs[0].abspath()) @feature('cs') @after_method('apply_cs', 'use_cs') def debug_cs(self): """ The C# targets may create .mdb or .pdb files:: def build(bld): bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdebug='full') # csdebug is a value in [True, 'full', 'pdbonly'] """ csdebug = getattr(self, 'csdebug', self.env.CSDEBUG) if not csdebug: return node = self.cs_task.outputs[0] if self.env.CS_NAME == 'mono': out = node.parent.find_or_declare(node.name + '.mdb') else: out = node.change_ext('.pdb') self.cs_task.outputs.append(out) try: self.install_task.source.append(out) except AttributeError: pass if csdebug == 'pdbonly': val = ['/debug+', '/debug:pdbonly'] elif csdebug == 'full': val = ['/debug+', '/debug:full'] else: val = ['/debug-'] self.env.append_value('CSFLAGS', val) class mcs(Task.Task): """ Compile C# files """ color = 'YELLOW' run_str = '${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' def exec_command(self, cmd, **kw): bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir try: tmp = None if isinstance(cmd, list) and len(' '.join(cmd)) >= 8192: program = cmd[0] #unquoted program name, otherwise exec_command will fail cmd = [self.quote_response_command(x) for x in cmd] (fd, tmp) = tempfile.mkstemp() os.write(fd, '\r\n'.join(i.replace('\\', '\\\\') for i in cmd[1:]).encode()) os.close(fd) cmd = [program, '@' + tmp] # no return here, that's on purpose ret = self.generator.bld.exec_command(cmd, **kw) finally: if tmp: try: os.remove(tmp) except OSError: pass # anti-virus and indexers can keep the files open -_- return ret def quote_response_command(self, flag): # /noconfig is not allowed when using response files if flag.lower() == '/noconfig': return '' if flag.find(' ') > -1: for x in ('/r:', '/reference:', '/resource:', '/lib:', '/out:'): if flag.startswith(x): flag = '%s"%s"' % (x, flag[len(x):]) break else: flag = '"%s"' % flag return flag def configure(conf): """ Find a C# compiler, set the variable MCS for the compiler and CS_NAME (mono or csc) """ csc = getattr(Options.options, 'cscbinary', None) if csc: conf.env.MCS = csc conf.find_program(['csc', 'mcs', 'gmcs'], var='MCS') conf.env.ASS_ST = '/r:%s' conf.env.RES_ST = '/resource:%s' conf.env.CS_NAME = 'csc' if str(conf.env.MCS).lower().find('mcs') > -1: conf.env.CS_NAME = 'mono' def options(opt): """ Add a command-line option for the configuration:: $ waf configure --with-csc-binary=/foo/bar/mcs """ opt.add_option('--with-csc-binary', type='string', dest='cscbinary') class fake_csshlib(Task.Task): """ Task used for reading a foreign .net assembly and adding the dependency on it """ color = 'YELLOW' inst_to = None def runnable_status(self): for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME @conf def read_csshlib(self, name, paths=[]): """ Read a foreign .net assembly for the *use* system:: def build(bld): bld.read_csshlib('ManagedLibrary.dll', paths=[bld.env.mylibrarypath]) bld(features='cs', source='Hi.cs', bintype='exe', gen='hi.exe', use='ManagedLibrary.dll') :param name: Name of the library :type name: string :param paths: Folders in which the library may be found :type paths: list of string :return: A task generator having the feature *fake_lib* which will call :py:func:`waflib.Tools.ccroot.process_lib` :rtype: :py:class:`waflib.TaskGen.task_gen` """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='csshlib') debian/waf-1.7/waflib/Tools/ar.py0000664000000000000000000000107512145745420013577 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) """ The **ar** program creates static libraries. This tool is almost always loaded from others (C, C++, D, etc) for static library support. """ from waflib.Configure import conf @conf def find_ar(conf): """Configuration helper used by C/C++ tools to enable the support for static libraries""" conf.load('ar') def configure(conf): """Find the ar program and set the default flags in ``conf.env.ARFLAGS``""" conf.find_program('ar', var='AR') conf.env.ARFLAGS = 'rcs' debian/waf-1.7/waflib/Tools/lua.py0000664000000000000000000000150212145745420013751 0ustar #!/usr/bin/env python # encoding: utf-8 # Sebastian Schlingmann, 2008 # Thomas Nagy, 2008-2010 (ita) """ Lua support. Compile *.lua* files into *.luac*:: def configure(conf): conf.load('lua') conf.env.LUADIR = '/usr/local/share/myapp/scripts/' def build(bld): bld(source='foo.lua') """ from waflib.TaskGen import extension from waflib import Task, Utils @extension('.lua') def add_lua(self, node): tsk = self.create_task('luac', node, node.change_ext('.luac')) inst_to = getattr(self, 'install_path', self.env.LUADIR and '${LUADIR}' or None) if inst_to: self.bld.install_files(inst_to, tsk.outputs) return tsk class luac(Task.Task): run_str = '${LUAC} -s -o ${TGT} ${SRC}' color = 'PINK' def configure(conf): """ Detect the luac compiler and set *conf.env.LUAC* """ conf.find_program('luac', var='LUAC') debian/waf-1.7/waflib/Tools/fc_scan.py0000664000000000000000000000602512145745420014571 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils, Task, TaskGen, Logs from waflib.TaskGen import feature, before_method, after_method, extension from waflib.Configure import conf INC_REGEX = """(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" MOD_REGEX = """(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" re_inc = re.compile(INC_REGEX, re.I) re_use = re.compile(USE_REGEX, re.I) re_mod = re.compile(MOD_REGEX, re.I) class fortran_parser(object): """ This parser will return: * the nodes corresponding to the module names that will be produced * the nodes corresponding to the include files used * the module names used by the fortran file """ def __init__(self, incpaths): self.seen = [] """Files already parsed""" self.nodes = [] """List of :py:class:`waflib.Node.Node` representing the dependencies to return""" self.names = [] """List of module names to return""" self.incpaths = incpaths """List of :py:class:`waflib.Node.Node` representing the include paths""" def find_deps(self, node): """ Parse a fortran file to read the dependencies used and provided :param node: fortran file to read :type node: :py:class:`waflib.Node.Node` :return: lists representing the includes, the modules used, and the modules created by a fortran file :rtype: tuple of list of strings """ txt = node.read() incs = [] uses = [] mods = [] for line in txt.splitlines(): # line by line regexp search? optimize? m = re_inc.search(line) if m: incs.append(m.group(1)) m = re_use.search(line) if m: uses.append(m.group(1)) m = re_mod.search(line) if m: mods.append(m.group(1)) return (incs, uses, mods) def start(self, node): """ Start the parsing. Use the stack self.waiting to hold the nodes to iterate on :param node: fortran file :type node: :py:class:`waflib.Node.Node` """ self.waiting = [node] while self.waiting: nd = self.waiting.pop(0) self.iter(nd) def iter(self, node): """ Process a single file in the search for dependencies, extract the files used the modules used, and the modules provided. """ path = node.abspath() incs, uses, mods = self.find_deps(node) for x in incs: if x in self.seen: continue self.seen.append(x) self.tryfind_header(x) for x in uses: name = "USE@%s" % x if not name in self.names: self.names.append(name) for x in mods: name = "MOD@%s" % x if not name in self.names: self.names.append(name) def tryfind_header(self, filename): """ Try to find an include and add it the nodes to process :param filename: file name :type filename: string """ found = None for n in self.incpaths: found = n.find_resource(filename) if found: self.nodes.append(found) self.waiting.append(found) break if not found: if not filename in self.names: self.names.append(filename) debian/waf-1.7/waflib/Tools/xlcxx.py0000664000000000000000000000315312145745420014342 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_xlcxx(conf): """ Detect the Aix C++ compiler """ cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX') cxx = conf.cmd_to_list(cxx) conf.get_xlc_version(cxx) conf.env.CXX_NAME = 'xlc++' conf.env.CXX = cxx @conf def xlcxx_common_flags(conf): """ Flags required for executing the Aix C++ compiler """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] # program v['LINKFLAGS_cxxprogram']= ['-Wl,-brtl'] v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-fPIC'] v['LINKFLAGS_cxxshlib'] = ['-G', '-Wl,-brtl,-bexpfull'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = [] v['cxxstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_xlcxx() conf.find_ar() conf.xlcxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/msvc.py0000664000000000000000000010543412145745420014151 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 (dv) # Tamas Pal, 2007 (folti) # Nicolas Mercier, 2009 # Matt Clarkson, 2012 """ Microsoft Visual C++/Intel C++ compiler support Usage:: $ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64" or:: def configure(conf): conf.env['MSVC_VERSIONS'] = ['msvc 10.0', 'msvc 9.0', 'msvc 8.0', 'msvc 7.1', 'msvc 7.0', 'msvc 6.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] conf.env['MSVC_TARGETS'] = ['x64'] conf.load('msvc') or:: def configure(conf): conf.load('msvc', funs='no_autodetect') conf.check_lib_msvc('gdi32') conf.check_libs_msvc('kernel32 user32') def build(bld): tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32') Platforms and targets will be tested in the order they appear; the first good configuration will be used. Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64 Compilers supported: * msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 11.0 (Visual Studio 2012) * wsdk => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0 * icl => Intel compiler, versions 9, 10, 11, 13 * winphone => Visual Studio to target Windows Phone 8 native (version 8.0 for now) * Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) * PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894) You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf. So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'. cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" Setting PYTHONUNBUFFERED gives the unbuffered output. """ import os, sys, re, tempfile from waflib import Utils, Task, Logs, Options, Errors from waflib.Logs import debug, warn from waflib.TaskGen import after_method, feature from waflib.Configure import conf from waflib.Tools import ccroot, c, cxx, ar, winres g_msvc_systemlibs = ''' aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp '''.split() """importlibs provided by MSVC/Platform SDK. Do NOT search them""" all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64'), ('x86_arm', 'arm') ] """List of msvc platforms""" all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] """List of wince platforms""" all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] """List of icl platforms""" def options(opt): opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') def setup_msvc(conf, versions, arch = False): platforms = getattr(Options.options, 'msvc_targets', '').split(',') if platforms == ['']: platforms=Utils.to_list(conf.env['MSVC_TARGETS']) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] desired_versions = getattr(Options.options, 'msvc_version', '').split(',') if desired_versions == ['']: desired_versions = conf.env['MSVC_VERSIONS'] or [v for v,_ in versions][::-1] versiondict = dict(versions) for version in desired_versions: try: targets = dict(versiondict [version]) for target in platforms: try: arch,(p1,p2,p3) = targets[target] compiler,revision = version.rsplit(' ', 1) if arch: return compiler,revision,p1,p2,p3,arch else: return compiler,revision,p1,p2,p3 except KeyError: continue except KeyError: continue conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') @conf def get_msvc_version(conf, compiler, version, target, vcvars): """ Create a bat file to obtain the location of the libraries :param compiler: ? :param version: ? :target: ? :vcvars: ? :return: the location of msvc, the location of include dirs, and the library paths :rtype: tuple of strings """ debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) batfile = conf.bldnode.make_node('waf-print-msvc.bat') batfile.write("""@echo off set INCLUDE= set LIB= call "%s" %s echo PATH=%%PATH%% echo INCLUDE=%%INCLUDE%% echo LIB=%%LIB%%;%%LIBPATH%% """ % (vcvars,target)) sout = conf.cmd_and_log(['cmd', '/E:on', '/V:on', '/C', batfile.abspath()]) lines = sout.splitlines() if not lines[0]: lines.pop(0) MSVC_PATH = MSVC_INCDIR = MSVC_LIBDIR = None for line in lines: if line.startswith('PATH='): path = line[5:] MSVC_PATH = path.split(';') elif line.startswith('INCLUDE='): MSVC_INCDIR = [i for i in line[8:].split(';') if i] elif line.startswith('LIB='): MSVC_LIBDIR = [i for i in line[4:].split(';') if i] if None in (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR): conf.fatal('msvc: Could not find a valid architecture for building (get_msvc_version_3)') # Check if the compiler is usable at all. # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. env = dict(os.environ) env.update(PATH = path) compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) cxx = conf.find_program(compiler_name, path_list=MSVC_PATH) cxx = conf.cmd_to_list(cxx) # delete CL if exists. because it could contain parameters wich can change cl's behaviour rather catastrophically. if 'CL' in env: del(env['CL']) try: try: conf.cmd_and_log(cxx + ['/help'], env=env) except Exception as e: debug('msvc: get_msvc_version: %r %r %r -> failure' % (compiler, version, target)) debug(str(e)) conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') else: debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) finally: conf.env[compiler_name] = '' return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) @conf def gather_wsdk_versions(conf, versions): """ Use winreg to add the msvc versions to the input list :param versions: list to modify :type versions: list """ version_pattern = re.compile('^v..?.?\...?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue try: msvc_version = Utils.winreg.OpenKey(all_versions, version) path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') except WindowsError: continue if os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): targets = [] for target,arch in all_msvc_platforms: try: targets.append((target, (arch, conf.get_msvc_version('wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))))) except conf.errors.ConfigurationError: pass versions.append(('wsdk ' + version[1:], targets)) def gather_wince_supported_platforms(): """ Checks SmartPhones SDKs :param versions: list to modify :type versions: list """ supported_wince_platforms = [] try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: ce_sdk = '' if not ce_sdk: return supported_wince_platforms ce_index = 0 while 1: try: sdk_device = Utils.winreg.EnumKey(ce_sdk, ce_index) except WindowsError: break ce_index = ce_index + 1 sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device) try: path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir') except WindowsError: try: path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation') path,xml = os.path.split(path) except WindowsError: continue path=str(path) path,device = os.path.split(path) if not device: path,device = os.path.split(path) for arch,compiler in all_wince_platforms: platforms = [] if os.path.isdir(os.path.join(path, device, 'Lib', arch)): platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch))) if platforms: supported_wince_platforms.append((device, platforms)) return supported_wince_platforms def gather_msvc_detected_versions(): #Detected MSVC versions! version_pattern = re.compile('^(\d\d?\.\d\d?)(Exp)?$') detected_versions = [] for vcver,vcvar in [('VCExpress','Exp'), ('VisualStudio','')]: try: prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\'+vcver all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) except WindowsError: try: prefix = 'SOFTWARE\\Microsoft\\'+vcver all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) except WindowsError: continue index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 match = version_pattern.match(version) if not match: continue else: versionnumber = float(match.group(1)) detected_versions.append((versionnumber, version+vcvar, prefix+"\\"+version)) def fun(tup): return tup[0] detected_versions.sort(key = fun) return detected_versions @conf def gather_msvc_targets(conf, versions, version, vc_path): #Looking for normal MSVC compilers! targets = [] if os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')): for target,realtarget in all_msvc_platforms[::-1]: try: targets.append((target, (realtarget, conf.get_msvc_version('msvc', version, target, os.path.join(vc_path, 'vcvarsall.bat'))))) except conf.errors.ConfigurationError: pass elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')): try: targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat'))))) except conf.errors.ConfigurationError: pass elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): try: targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat'))))) except conf.errors.ConfigurationError: pass if targets: versions.append(('msvc '+ version, targets)) @conf def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): #Looking for Win CE compilers! for device,platforms in supported_platforms: cetargets = [] for platform,compiler,include,lib in platforms: winCEpath = os.path.join(vc_path, 'ce') if not os.path.isdir(winCEpath): continue try: common_bindirs,_1,_2 = conf.get_msvc_version('msvc', version, 'x86', vsvars) except conf.errors.ConfigurationError: continue if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + common_bindirs incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] cetargets.append((platform, (platform, (bindirs,incdirs,libdirs)))) if cetargets: versions.append((device + ' ' + version, cetargets)) @conf def gather_winphone_targets(conf, versions, version, vc_path, vsvars): #Looking for WinPhone compilers targets = [] for target,realtarget in all_msvc_platforms[::-1]: try: targets.append((target, (realtarget, conf.get_msvc_version('winphone', version, target, vsvars)))) except conf.errors.ConfigurationError as e: pass if targets: versions.append(('winphone '+ version, targets)) @conf def gather_msvc_versions(conf, versions): vc_paths = [] for (v,version,reg) in gather_msvc_detected_versions(): try: try: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") except WindowsError: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir') vc_paths.append((version, os.path.abspath(str(path)))) except WindowsError: continue wince_supported_platforms = gather_wince_supported_platforms() for version,vc_path in vc_paths: vs_path = os.path.dirname(vc_path) vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat') if wince_supported_platforms and os.path.isfile(vsvars): conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms) vsvars = os.path.join(vs_path, 'VC', 'WPSDK', 'WP80', 'vcvarsphoneall.bat') if os.path.isfile(vsvars): conf.gather_winphone_targets(versions, '8.0', vc_path, vsvars) for version,vc_path in vc_paths: vs_path = os.path.dirname(vc_path) conf.gather_msvc_targets(versions, version, vc_path) @conf def gather_icl_versions(conf, versions): """ Checks ICL compilers :param versions: list to modify :type versions: list """ version_pattern = re.compile('^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') except WindowsError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') except WindowsError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue targets = [] for target,arch in all_icl_platforms: try: if target=='intel64': targetDir='EM64T_NATIVE' else: targetDir=target Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version) path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') batch_file=os.path.join(path,'bin','iclvars.bat') if os.path.isfile(batch_file): try: targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file)))) except conf.errors.ConfigurationError: pass except WindowsError: pass for target,arch in all_icl_platforms: try: icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') batch_file=os.path.join(path,'bin','iclvars.bat') if os.path.isfile(batch_file): try: targets.append((target, (arch, conf.get_msvc_version('intel', version, target, batch_file)))) except conf.errors.ConfigurationError: pass except WindowsError: continue major = version[0:2] versions.append(('intel ' + major, targets)) @conf def gather_intel_composer_versions(conf, versions): """ Checks ICL compilers that are part of Intel Composer Suites :param versions: list to modify :type versions: list """ version_pattern = re.compile('^...?.?\...?.?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') except WindowsError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites') except WindowsError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue targets = [] for target,arch in all_icl_platforms: try: if target=='intel64': targetDir='EM64T_NATIVE' else: targetDir=target try: defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) except WindowsError: if targetDir=='EM64T_NATIVE': defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') else: raise WindowsError uid,type = Utils.winreg.QueryValueEx(defaults, 'SubKey') Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') batch_file=os.path.join(path,'bin','iclvars.bat') if os.path.isfile(batch_file): try: targets.append((target,(arch,conf.get_msvc_version('intel',version,target,batch_file)))) except conf.errors.ConfigurationError as e: pass # The intel compilervar_arch.bat is broken when used with Visual Studio Express 2012 # http://software.intel.com/en-us/forums/topic/328487 compilervars_warning_attr = '_compilervars_warning_key' if version[0:2] == '13' and getattr(conf, compilervars_warning_attr, True): setattr(conf, compilervars_warning_attr, False) patch_url = 'http://software.intel.com/en-us/forums/topic/328487' compilervars_arch = os.path.join(path, 'bin', 'compilervars_arch.bat') vs_express_path = os.environ['VS110COMNTOOLS'] + r'..\IDE\VSWinExpress.exe' dev_env_path = os.environ['VS110COMNTOOLS'] + r'..\IDE\devenv.exe' if (r'if exist "%VS110COMNTOOLS%..\IDE\VSWinExpress.exe"' in Utils.readf(compilervars_arch) and not os.path.exists(vs_express_path) and not os.path.exists(dev_env_path)): Logs.warn(('The Intel compilervar_arch.bat only checks for one Visual Studio SKU ' '(VSWinExpress.exe) but it does not seem to be installed at %r. ' 'The intel command line set up will fail to configure unless the file %r' 'is patched. See: %s') % (vs_express_path, compilervars_arch, patch_url)) except WindowsError: pass major = version[0:2] versions.append(('intel ' + major, targets)) @conf def get_msvc_versions(conf): """ :return: list of compilers installed :rtype: list of string """ if not conf.env['MSVC_INSTALLED_VERSIONS']: lst = [] conf.gather_icl_versions(lst) conf.gather_intel_composer_versions(lst) conf.gather_wsdk_versions(lst) conf.gather_msvc_versions(lst) conf.env['MSVC_INSTALLED_VERSIONS'] = lst return conf.env['MSVC_INSTALLED_VERSIONS'] @conf def print_all_msvc_detected(conf): """ Print the contents of *conf.env.MSVC_INSTALLED_VERSIONS* """ for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']: Logs.info(version) for target,l in targets: Logs.info("\t"+target) @conf def detect_msvc(conf, arch = False): versions = get_msvc_versions(conf) return setup_msvc(conf, versions, arch) @conf def find_lt_names_msvc(self, libname, is_static=False): """ Win32/MSVC specific code to glean out information from libtool la files. this function is not attached to the task_gen class """ lt_names=[ 'lib%s.la' % libname, '%s.la' % libname, ] for path in self.env['LIBPATH']: for la in lt_names: laf=os.path.join(path,la) dll=None if os.path.exists(laf): ltdict = Utils.read_la_file(laf) lt_libdir=None if ltdict.get('libdir', ''): lt_libdir = ltdict['libdir'] if not is_static and ltdict.get('library_names', ''): dllnames=ltdict['library_names'].split() dll=dllnames[0].lower() dll=re.sub('\.dll$', '', dll) return (lt_libdir, dll, False) elif ltdict.get('old_library', ''): olib=ltdict['old_library'] if os.path.exists(os.path.join(path,olib)): return (path, olib, True) elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)): return (lt_libdir, olib, True) else: return (None, olib, True) else: raise self.errors.WafError('invalid libtool object file: %s' % laf) return (None, None, None) @conf def libname_msvc(self, libname, is_static=False): lib = libname.lower() lib = re.sub('\.lib$','',lib) if lib in g_msvc_systemlibs: return lib lib=re.sub('^lib','',lib) if lib == 'm': return None (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) if lt_path != None and lt_libname != None: if lt_static == True: # file existance check has been made by find_lt_names return os.path.join(lt_path,lt_libname) if lt_path != None: _libpaths=[lt_path] + self.env['LIBPATH'] else: _libpaths=self.env['LIBPATH'] static_libs=[ 'lib%ss.lib' % lib, 'lib%s.lib' % lib, '%ss.lib' % lib, '%s.lib' %lib, ] dynamic_libs=[ 'lib%s.dll.lib' % lib, 'lib%s.dll.a' % lib, '%s.dll.lib' % lib, '%s.dll.a' % lib, 'lib%s_d.lib' % lib, '%s_d.lib' % lib, '%s.lib' %lib, ] libnames=static_libs if not is_static: libnames=dynamic_libs + static_libs for path in _libpaths: for libn in libnames: if os.path.exists(os.path.join(path, libn)): debug('msvc: lib found: %s' % os.path.join(path,libn)) return re.sub('\.lib$', '',libn) #if no lib can be found, just return the libname as msvc expects it self.fatal("The library %r could not be found" % libname) return re.sub('\.lib$', '', libname) @conf def check_lib_msvc(self, libname, is_static=False, uselib_store=None): """ Ideally we should be able to place the lib in the right env var, either STLIB or LIB, but we don't distinguish static libs from shared libs. This is ok since msvc doesn't have any special linker flag to select static libs (no env['STLIB_MARKER']) """ libn = self.libname_msvc(libname, is_static) if not uselib_store: uselib_store = libname.upper() if False and is_static: # disabled self.env['STLIB_' + uselib_store] = [libn] else: self.env['LIB_' + uselib_store] = [libn] @conf def check_libs_msvc(self, libnames, is_static=False): for libname in Utils.to_list(libnames): self.check_lib_msvc(libname, is_static) def configure(conf): """ Configuration methods to call for detecting msvc """ conf.autodetect(True) conf.find_msvc() conf.msvc_common_flags() conf.cc_load_tools() conf.cxx_load_tools() conf.cc_add_flags() conf.cxx_add_flags() conf.link_add_flags() conf.visual_studio_add_flags() @conf def no_autodetect(conf): conf.env.NO_MSVC_DETECT = 1 configure(conf) @conf def autodetect(conf, arch = False): v = conf.env if v.NO_MSVC_DETECT: return if arch: compiler, version, path, includes, libdirs, arch = conf.detect_msvc(True) v['DEST_CPU'] = arch else: compiler, version, path, includes, libdirs = conf.detect_msvc() v['PATH'] = path v['INCLUDES'] = includes v['LIBPATH'] = libdirs v['MSVC_COMPILER'] = compiler try: v['MSVC_VERSION'] = float(version) except Exception: v['MSVC_VERSION'] = float(version[:-3]) def _get_prog_names(conf, compiler): if compiler=='intel': compiler_name = 'ICL' linker_name = 'XILINK' lib_name = 'XILIB' else: # assumes CL.exe compiler_name = 'CL' linker_name = 'LINK' lib_name = 'LIB' return compiler_name, linker_name, lib_name @conf def find_msvc(conf): """Due to path format limitations, limit operation only to native Win32. Yeah it sucks.""" if sys.platform == 'cygwin': conf.fatal('MSVC module does not work under cygwin Python!') # the autodetection is supposed to be performed before entering in this method v = conf.env path = v['PATH'] compiler = v['MSVC_COMPILER'] version = v['MSVC_VERSION'] compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11) # compiler cxx = None if v['CXX']: cxx = v['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] cxx = conf.find_program(compiler_name, var='CXX', path_list=path) cxx = conf.cmd_to_list(cxx) # before setting anything, check if the compiler is really msvc env = dict(conf.environ) if path: env.update(PATH = ';'.join(path)) if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): conf.fatal('the msvc compiler could not be identified') # c/c++ compiler v['CC'] = v['CXX'] = cxx v['CC_NAME'] = v['CXX_NAME'] = 'msvc' # linker if not v['LINK_CXX']: link = conf.find_program(linker_name, path_list=path) if link: v['LINK_CXX'] = link else: conf.fatal('%s was not found (linker)' % linker_name) v['LINK'] = link if not v['LINK_CC']: v['LINK_CC'] = v['LINK_CXX'] # staticlib linker if not v['AR']: stliblink = conf.find_program(lib_name, path_list=path, var='AR') if not stliblink: return v['ARFLAGS'] = ['/NOLOGO'] # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later if v.MSVC_MANIFEST: conf.find_program('MT', path_list=path, var='MT') v['MTFLAGS'] = ['/NOLOGO'] try: conf.load('winres') except Errors.WafError: warn('Resource compiler not found. Compiling resource file is disabled') @conf def visual_studio_add_flags(self): """visual studio flags found in the system environment""" v = self.env try: v.prepend_value('INCLUDES', [x for x in self.environ['INCLUDE'].split(';') if x]) # notice the 'S' except Exception: pass try: v.prepend_value('LIBPATH', [x for x in self.environ['LIB'].split(';') if x]) except Exception: pass @conf def msvc_common_flags(conf): """ Setup the flags required for executing the msvc compiler """ v = conf.env v['DEST_BINFMT'] = 'pe' v.append_value('CFLAGS', ['/nologo']) v.append_value('CXXFLAGS', ['/nologo']) v['DEFINES_ST'] = '/D%s' v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['/c', '/Fo'] if v['MSVC_VERSION'] >= 8: v['CC_TGT_F']= ['/FC'] + v['CC_TGT_F'] v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['/c', '/Fo'] if v['MSVC_VERSION'] >= 8: v['CXX_TGT_F']= ['/FC'] + v['CXX_TGT_F'] v['CPPPATH_ST'] = '/I%s' # template for adding include paths v['AR_TGT_F'] = v['CCLNK_TGT_F'] = v['CXXLNK_TGT_F'] = '/OUT:' # Subsystem specific flags v['CFLAGS_CONSOLE'] = v['CXXFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE'] v['CFLAGS_NATIVE'] = v['CXXFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE'] v['CFLAGS_POSIX'] = v['CXXFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX'] v['CFLAGS_WINDOWS'] = v['CXXFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS'] v['CFLAGS_WINDOWSCE'] = v['CXXFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE'] # CRT specific flags v['CFLAGS_CRT_MULTITHREADED'] = v['CXXFLAGS_CRT_MULTITHREADED'] = ['/MT'] v['CFLAGS_CRT_MULTITHREADED_DLL'] = v['CXXFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD'] v['CFLAGS_CRT_MULTITHREADED_DBG'] = v['CXXFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd'] v['CFLAGS_CRT_MULTITHREADED_DLL_DBG'] = v['CXXFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd'] # linker v['LIB_ST'] = '%s.lib' # template for adding shared libs v['LIBPATH_ST'] = '/LIBPATH:%s' # template for adding libpaths v['STLIB_ST'] = '%s.lib' v['STLIBPATH_ST'] = '/LIBPATH:%s' v.append_value('LINKFLAGS', ['/NOLOGO']) if v['MSVC_MANIFEST']: v.append_value('LINKFLAGS', ['/MANIFEST']) # shared library v['CFLAGS_cshlib'] = [] v['CXXFLAGS_cxxshlib'] = [] v['LINKFLAGS_cshlib'] = v['LINKFLAGS_cxxshlib'] = ['/DLL'] v['cshlib_PATTERN'] = v['cxxshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = '%s.lib' v['IMPLIB_ST'] = '/IMPLIB:%s' # static library v['LINKFLAGS_cstlib'] = [] v['cstlib_PATTERN'] = v['cxxstlib_PATTERN'] = '%s.lib' # program v['cprogram_PATTERN'] = v['cxxprogram_PATTERN'] = '%s.exe' ####################################################################################################### ##### conf above, build below @after_method('apply_link') @feature('c', 'cxx') def apply_flags_msvc(self): """ Add additional flags implied by msvc, such as subsystems and pdb files:: def build(bld): bld.stlib(source='main.c', target='bar', subsystem='gruik') """ if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None): return is_static = isinstance(self.link_task, ccroot.stlink_task) subsystem = getattr(self, 'subsystem', '') if subsystem: subsystem = '/subsystem:%s' % subsystem flags = is_static and 'ARFLAGS' or 'LINKFLAGS' self.env.append_value(flags, subsystem) if not is_static: for f in self.env.LINKFLAGS: d = f.lower() if d[1:] == 'debug': pdbnode = self.link_task.outputs[0].change_ext('.pdb') self.link_task.outputs.append(pdbnode) try: self.install_task.source.append(pdbnode) except AttributeError: pass break # split the manifest file processing from the link task, like for the rc processing @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib') @after_method('apply_link') def apply_manifest(self): """ Special linker for MSVC with support for embedding manifests into DLL's and executables compiled by Visual Studio 2005 or probably later. Without the manifest file, the binaries are unusable. See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx """ if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None): out_node = self.link_task.outputs[0] man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') self.link_task.outputs.append(man_node) self.link_task.do_manifest = True def exec_mf(self): """ Create the manifest file """ env = self.env mtool = env['MT'] if not mtool: return 0 self.do_manifest = False outfile = self.outputs[0].abspath() manifest = None for out_node in self.outputs: if out_node.name.endswith('.manifest'): manifest = out_node.abspath() break if manifest is None: # Should never get here. If we do, it means the manifest file was # never added to the outputs list, thus we don't have a manifest file # to embed, so we just return. return 0 # embedding mode. Different for EXE's and DLL's. # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx mode = '' if 'cprogram' in self.generator.features or 'cxxprogram' in self.generator.features: mode = '1' elif 'cshlib' in self.generator.features or 'cxxshlib' in self.generator.features: mode = '2' debug('msvc: embedding manifest in mode %r' % mode) lst = [] lst.append(env['MT']) lst.extend(Utils.to_list(env['MTFLAGS'])) lst.extend(['-manifest', manifest]) lst.append('-outputresource:%s;%s' % (outfile, mode)) lst = [lst] return self.exec_command(*lst) def quote_response_command(self, flag): if flag.find(' ') > -1: for x in ('/LIBPATH:', '/IMPLIB:', '/OUT:', '/I'): if flag.startswith(x): flag = '%s"%s"' % (x, flag[len(x):]) break else: flag = '"%s"' % flag return flag def exec_response_command(self, cmd, **kw): # not public yet try: tmp = None if sys.platform.startswith('win') and isinstance(cmd, list) and len(' '.join(cmd)) >= 8192: program = cmd[0] #unquoted program name, otherwise exec_command will fail cmd = [self.quote_response_command(x) for x in cmd] (fd, tmp) = tempfile.mkstemp() os.write(fd, '\r\n'.join(i.replace('\\', '\\\\') for i in cmd[1:]).encode()) os.close(fd) cmd = [program, '@' + tmp] # no return here, that's on purpose ret = self.generator.bld.exec_command(cmd, **kw) finally: if tmp: try: os.remove(tmp) except OSError: pass # anti-virus and indexers can keep the files open -_- return ret ########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token def exec_command_msvc(self, *k, **kw): """ Change the command-line execution for msvc programs. Instead of quoting all the paths and keep using the shell, we can just join the options msvc is interested in """ assert self.env['CC_NAME'] == 'msvc' if isinstance(k[0], list): lst = [] carry = '' for a in k[0]: if a == '/Fo' or a == '/doc' or a[-1] == ':': carry = a else: lst.append(carry + a) carry = '' k = [lst] if self.env['PATH']: env = dict(self.env.env or os.environ) env.update(PATH = ';'.join(self.env['PATH'])) kw['env'] = env bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir ret = self.exec_response_command(k[0], **kw) if not ret and getattr(self, 'do_manifest', None): ret = self.exec_mf() return ret def wrap_class(class_name): """ Manifest file processing and @response file workaround for command-line length limits on Windows systems The indicated task class is replaced by a subclass to prevent conflicts in case the class is wrapped more than once """ cls = Task.classes.get(class_name, None) if not cls: return None derived_class = type(class_name, (cls,), {}) def exec_command(self, *k, **kw): if self.env['CC_NAME'] == 'msvc': return self.exec_command_msvc(*k, **kw) else: return super(derived_class, self).exec_command(*k, **kw) # Chain-up monkeypatch needed since exec_command() is in base class API derived_class.exec_command = exec_command # No chain-up behavior needed since the following methods aren't in # base class API derived_class.exec_response_command = exec_response_command derived_class.quote_response_command = quote_response_command derived_class.exec_command_msvc = exec_command_msvc derived_class.exec_mf = exec_mf return derived_class for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): wrap_class(k) def make_winapp(self, family): append = self.env.append_unique append('DEFINES', 'WINAPI_FAMILY=%s' % family) append('CXXFLAGS', '/ZW') append('CXXFLAGS', '/TP') for lib_path in self.env.LIBPATH: append('CXXFLAGS','/AI%s'%lib_path) @feature('winphoneapp') @after_method('process_use') @after_method('propagate_uselib_vars') def make_winphone_app(self): make_winapp(self, 'WINAPI_FAMILY_PHONE_APP') conf.env.append_unique('LINKFLAGS', '/NODEFAULTLIB:ole32.lib') conf.env.append_unique('LINKFLAGS', 'PhoneAppModelHost.lib') @feature('winapp') @after_method('process_use') @after_method('propagate_uselib_vars') def make_windows_app(self): make_winapp(self, 'WINAPI_FAMILY_DESKTOP_APP') debian/waf-1.7/waflib/Tools/dbus.py0000664000000000000000000000403112145745420014125 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ Compile dbus files with **dbus-binding-tool** Typical usage:: def options(opt): opt.load('compiler_c dbus') def configure(conf): conf.load('compiler_c dbus') def build(bld): tg = bld.program( includes = '.', source = bld.path.ant_glob('*.c'), target = 'gnome-hello') tg.add_dbus_file('test.xml', 'test_prefix', 'glib-server') """ from waflib import Task, Errors from waflib.TaskGen import taskgen_method, before_method @taskgen_method def add_dbus_file(self, filename, prefix, mode): """ Add a dbus file to the list of dbus files to process. Store them in the attribute *dbus_lst*. :param filename: xml file to compile :type filename: string :param prefix: dbus binding tool prefix (--prefix=prefix) :type prefix: string :param mode: dbus binding tool mode (--mode=mode) :type mode: string """ if not hasattr(self, 'dbus_lst'): self.dbus_lst = [] if not 'process_dbus' in self.meths: self.meths.append('process_dbus') self.dbus_lst.append([filename, prefix, mode]) @before_method('apply_core') def process_dbus(self): """ Process the dbus files stored in the attribute *dbus_lst* to create :py:class:`waflib.Tools.dbus.dbus_binding_tool` instances. """ for filename, prefix, mode in getattr(self, 'dbus_lst', []): node = self.path.find_resource(filename) if not node: raise Errors.WafError('file not found ' + filename) tsk = self.create_task('dbus_binding_tool', node, node.change_ext('.h')) tsk.env.DBUS_BINDING_TOOL_PREFIX = prefix tsk.env.DBUS_BINDING_TOOL_MODE = mode class dbus_binding_tool(Task.Task): """ Compile a dbus file """ color = 'BLUE' ext_out = ['.h'] run_str = '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}' shell = True # temporary workaround for #795 def configure(conf): """ Detect the program dbus-binding-tool and set the *conf.env.DBUS_BINDING_TOOL* """ dbus_binding_tool = conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') debian/waf-1.7/waflib/Tools/c_aliases.py0000664000000000000000000000566012145745420015124 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "base for all c/c++ programs and libraries" import os, sys, re from waflib import Utils, Build from waflib.Configure import conf def get_extensions(lst): """ :param lst: files to process :list lst: list of string or :py:class:`waflib.Node.Node` :return: list of file extensions :rtype: list of string """ ret = [] for x in Utils.to_list(lst): try: if not isinstance(x, str): x = x.name ret.append(x[x.rfind('.') + 1:]) except Exception: pass return ret def sniff_features(**kw): """ Look at the source files and return the features for a task generator (mainly cc and cxx):: snif_features(source=['foo.c', 'foo.cxx'], type='shlib') # returns ['cxx', 'c', 'cxxshlib', 'cshlib'] :param source: source files to process :type source: list of string or :py:class:`waflib.Node.Node` :param type: object type in *program*, *shlib* or *stlib* :type type: string :return: the list of features for a task generator processing the source files :rtype: list of string """ exts = get_extensions(kw['source']) type = kw['_type'] feats = [] # watch the order, cxx will have the precedence if 'cxx' in exts or 'cpp' in exts or 'c++' in exts or 'cc' in exts or 'C' in exts: feats.append('cxx') if 'c' in exts or 'vala' in exts: feats.append('c') if 'd' in exts: feats.append('d') if 'java' in exts: feats.append('java') if 'java' in exts: return 'java' if type in ['program', 'shlib', 'stlib']: for x in feats: if x in ['cxx', 'd', 'c']: feats.append(x + type) return feats def set_features(kw, _type): kw['_type'] = _type kw['features'] = Utils.to_list(kw.get('features', [])) + Utils.to_list(sniff_features(**kw)) @conf def program(bld, *k, **kw): """ Alias for creating programs by looking at the file extensions:: def build(bld): bld.program(source='foo.c', target='app') # equivalent to: # bld(features='c cprogram', source='foo.c', target='app') """ set_features(kw, 'program') return bld(*k, **kw) @conf def shlib(bld, *k, **kw): """ Alias for creating shared libraries by looking at the file extensions:: def build(bld): bld.shlib(source='foo.c', target='app') # equivalent to: # bld(features='c cshlib', source='foo.c', target='app') """ set_features(kw, 'shlib') return bld(*k, **kw) @conf def stlib(bld, *k, **kw): """ Alias for creating static libraries by looking at the file extensions:: def build(bld): bld.stlib(source='foo.cpp', target='app') # equivalent to: # bld(features='cxx cxxstlib', source='foo.cpp', target='app') """ set_features(kw, 'stlib') return bld(*k, **kw) @conf def objects(bld, *k, **kw): """ Alias for creating object files by looking at the file extensions:: def build(bld): bld.objects(source='foo.c', target='app') # equivalent to: # bld(features='c', source='foo.c', target='app') """ set_features(kw, 'objects') return bld(*k, **kw) debian/waf-1.7/waflib/Tools/g95.py0000664000000000000000000000302712145745420013600 0ustar #! /usr/bin/env python # encoding: utf-8 # KWS 2010 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan, ar from waflib.Configure import conf @conf def find_g95(conf): fc = conf.find_program('g95', var='FC') fc = conf.cmd_to_list(fc) conf.get_g95_version(fc) conf.env.FC_NAME = 'G95' @conf def g95_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC'] v['FORTRANMODFLAG'] = ['-fmod=', ''] # template for module path v['FCFLAGS_DEBUG'] = ['-Werror'] # why not @conf def g95_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def g95_modifier_cygwin(conf): fc_config.fortran_modifier_cygwin(conf) @conf def g95_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def g95_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() g95_modifier_func = getattr(conf, 'g95_modifier_' + dest_os, None) if g95_modifier_func: g95_modifier_func() @conf def get_g95_version(conf, fc): """get the compiler version""" version_re = re.compile(r"g95\s*(?P\d*)\.(?P\d*)").search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('cannot determine g95 version') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_g95() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.g95_flags() conf.g95_modifier_platform() debian/waf-1.7/waflib/Tools/ruby.py0000664000000000000000000001275012145745420014160 0ustar #!/usr/bin/env python # encoding: utf-8 # daniel.svensson at purplescout.se 2008 # Thomas Nagy 2010 (ita) """ Support for Ruby extensions. A C/C++ compiler is required:: def options(opt): opt.load('compiler_c ruby') def configure(conf): conf.load('compiler_c ruby') conf.check_ruby_version((1,8,0)) conf.check_ruby_ext_devel() conf.check_ruby_module('libxml') def build(bld): bld( features = 'c cshlib rubyext', source = 'rb_mytest.c', target = 'mytest_ext', install_path = '${ARCHDIR_RUBY}') bld.install_files('${LIBDIR_RUBY}', 'Mytest.rb') """ import os from waflib import Task, Options, Utils from waflib.TaskGen import before_method, feature, after_method, Task, extension from waflib.Configure import conf @feature('rubyext') @before_method('apply_incpaths', 'apply_lib_vars', 'apply_bundle', 'apply_link') def init_rubyext(self): """ Add required variables for ruby extensions """ self.install_path = '${ARCHDIR_RUBY}' self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'RUBY' in self.uselib: self.uselib.append('RUBY') if not 'RUBYEXT' in self.uselib: self.uselib.append('RUBYEXT') @feature('rubyext') @before_method('apply_link', 'propagate_uselib') def apply_ruby_so_name(self): """ Strip the *lib* prefix from ruby extensions """ self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['rubyext_PATTERN'] @conf def check_ruby_version(self, minver=()): """ Checks if ruby is installed. If installed the variable RUBY will be set in environment. The ruby binary can be overridden by ``--with-ruby-binary`` command-line option. """ if Options.options.rubybinary: self.env.RUBY = Options.options.rubybinary else: self.find_program('ruby', var='RUBY') ruby = self.env.RUBY try: version = self.cmd_and_log([ruby, '-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() except Exception: self.fatal('could not determine ruby version') self.env.RUBY_VERSION = version try: ver = tuple(map(int, version.split("."))) except Exception: self.fatal('unsupported ruby version %r' % version) cver = '' if minver: if ver < minver: self.fatal('ruby is too old %r' % ver) cver = '.'.join([str(x) for x in minver]) else: cver = ver self.msg('Checking for ruby version %s' % str(minver or ''), cver) @conf def check_ruby_ext_devel(self): """ Check if a ruby extension can be created """ if not self.env.RUBY: self.fatal('ruby detection is required first') if not self.env.CC_NAME and not self.env.CXX_NAME: self.fatal('load a c/c++ compiler first') version = tuple(map(int, self.env.RUBY_VERSION.split("."))) def read_out(cmd): return Utils.to_list(self.cmd_and_log([self.env.RUBY, '-rrbconfig', '-e', cmd])) def read_config(key): return read_out('puts Config::CONFIG[%r]' % key) ruby = self.env['RUBY'] archdir = read_config('archdir') cpppath = archdir if version >= (1, 9, 0): ruby_hdrdir = read_config('rubyhdrdir') cpppath += ruby_hdrdir cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] self.check(header_name='ruby.h', includes=cpppath, errmsg='could not find ruby header file') self.env.LIBPATH_RUBYEXT = read_config('libdir') self.env.LIBPATH_RUBYEXT += archdir self.env.INCLUDES_RUBYEXT = cpppath self.env.CFLAGS_RUBYEXT = read_config('CCDLFLAGS') self.env.rubyext_PATTERN = '%s.' + read_config('DLEXT')[0] # ok this is really stupid, but the command and flags are combined. # so we try to find the first argument... flags = read_config('LDSHARED') while flags and flags[0][0] != '-': flags = flags[1:] # we also want to strip out the deprecated ppc flags if len(flags) > 1 and flags[1] == "ppc": flags = flags[2:] self.env.LINKFLAGS_RUBYEXT = flags self.env.LINKFLAGS_RUBYEXT += read_config('LIBS') self.env.LINKFLAGS_RUBYEXT += read_config('LIBRUBYARG_SHARED') if Options.options.rubyarchdir: self.env.ARCHDIR_RUBY = Options.options.rubyarchdir else: self.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] if Options.options.rubylibdir: self.env.LIBDIR_RUBY = Options.options.rubylibdir else: self.env.LIBDIR_RUBY = read_config('sitelibdir')[0] @conf def check_ruby_module(self, module_name): """ Check if the selected ruby interpreter can require the given ruby module:: def configure(conf): conf.check_ruby_module('libxml') :param module_name: module :type module_name: string """ self.start_msg('Ruby module %s' % module_name) try: self.cmd_and_log([self.env['RUBY'], '-e', 'require \'%s\';puts 1' % module_name]) except Exception: self.end_msg(False) self.fatal('Could not find the ruby module %r' % module_name) self.end_msg(True) @extension('.rb') def process(self, node): tsk = self.create_task('run_ruby', node) class run_ruby(Task.Task): """ Task to run ruby files detected by file extension .rb:: def options(opt): opt.load('ruby') def configure(ctx): ctx.check_ruby_version() def build(bld): bld.env['RBFLAGS'] = '-e puts "hello world"' bld(source='a_ruby_file.rb') """ run_str = '${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' def options(opt): """ Add the ``--with-ruby-archdir``, ``--with-ruby-libdir`` and ``--with-ruby-binary`` options """ opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') debian/waf-1.7/waflib/Tools/winres.py0000664000000000000000000000603412145745420014504 0ustar #!/usr/bin/env python # encoding: utf-8 # Brant Young, 2007 "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" import re, traceback from waflib import Task, Logs, Utils from waflib.TaskGen import extension from waflib.Tools import c_preproc @extension('.rc') def rc_file(self, node): """ Bind the .rc extension to a winrc task """ obj_ext = '.rc.o' if self.env['WINRC_TGT_F'] == '/fo': obj_ext = '.res' rctask = self.create_task('winrc', node, node.change_ext(obj_ext)) try: self.compiled_tasks.append(rctask) except AttributeError: self.compiled_tasks = [rctask] re_lines = re.compile( '(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\ '(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)', re.IGNORECASE | re.MULTILINE) class rc_parser(c_preproc.c_parser): def filter_comments(self, filepath): code = Utils.readf(filepath) if c_preproc.use_trigraphs: for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) ret = [] for m in re.finditer(re_lines, code): if m.group(2): ret.append((m.group(2), m.group(3))) else: ret.append(('include', m.group(5))) return ret def addlines(self, node): self.currentnode_stack.append(node.parent) filepath = node.abspath() self.count_files += 1 if self.count_files > c_preproc.recursion_limit: raise c_preproc.PreprocError("recursion limit exceeded") pc = self.parse_cache Logs.debug('preproc: reading file %r', filepath) try: lns = pc[filepath] except KeyError: pass else: self.lines.extend(lns) return try: lines = self.filter_comments(filepath) lines.append((c_preproc.POPFILE, '')) lines.reverse() pc[filepath] = lines self.lines.extend(lines) except IOError: raise c_preproc.PreprocError("could not read the file %s" % filepath) except Exception: if Logs.verbose > 0: Logs.error("parsing %s failed" % filepath) traceback.print_exc() class winrc(Task.Task): """ Task for compiling resource files """ run_str = '${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' color = 'BLUE' def scan(self): tmp = rc_parser(self.generator.includes_nodes) tmp.start(self.inputs[0], self.env) nodes = tmp.nodes names = tmp.names if Logs.verbose: Logs.debug('deps: deps for %s: %r; unresolved %r' % (str(self), nodes, names)) return (nodes, names) def configure(conf): """ Detect the programs RC or windres, depending on the C/C++ compiler in use """ v = conf.env v['WINRC_TGT_F'] = '-o' v['WINRC_SRC_F'] = '-i' # find rc.exe if not conf.env.WINRC: if v.CC_NAME == 'msvc': conf.find_program('RC', var='WINRC', path_list = v['PATH']) v['WINRC_TGT_F'] = '/fo' v['WINRC_SRC_F'] = '' else: conf.find_program('windres', var='WINRC', path_list = v['PATH']) if not conf.env.WINRC: conf.fatal('winrc was not found!') v['WINRCFLAGS'] = [] debian/waf-1.7/waflib/Tools/suncc.py0000664000000000000000000000335312145745420014311 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_scc(conf): """ Detect the Sun C compiler """ v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('cc', var='CC') if not cc: conf.fatal('Could not find a Sun C compiler') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-flags']) except Exception: conf.fatal('%r is not a Sun compiler' % cc) v['CC'] = cc v['CC_NAME'] = 'sun' @conf def scc_common_flags(conf): """ Flags required for executing the sun C compiler """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STLIB_MARKER'] = '-Bstatic' # program v['cprogram_PATTERN'] = '%s' # shared library v['CFLAGS_cshlib'] = ['-Kpic', '-DPIC'] v['LINKFLAGS_cshlib'] = ['-G'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = ['-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_scc() conf.find_ar() conf.scc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/icpc.py0000664000000000000000000000162112145745420014110 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2009-2010 (ita) """ Detect the Intel C++ compiler """ import os, sys from waflib.Tools import ccroot, ar, gxx from waflib.Configure import conf @conf def find_icpc(conf): """ Find the program icpc, and execute it to ensure it really is icpc """ if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') v = conf.env cxx = None if v['CXX']: cxx = v['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] if not cxx: cxx = conf.find_program('icpc', var='CXX') if not cxx: conf.fatal('Intel C++ Compiler (icpc) was not found') cxx = conf.cmd_to_list(cxx) conf.get_cc_version(cxx, icc=True) v['CXX'] = cxx v['CXX_NAME'] = 'icc' def configure(conf): conf.find_icpc() conf.find_ar() conf.gxx_common_flags() conf.gxx_modifier_platform() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/dmd.py0000664000000000000000000000412712145745420013742 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2008-2010 (ita) import sys from waflib.Tools import ar, d from waflib.Configure import conf @conf def find_dmd(conf): """ Find the program *dmd*, *dmd2*, or *ldc* and set the variable *D* """ conf.find_program(['dmd', 'dmd2', 'ldc'], var='D') # make sure that we're dealing with dmd1, dmd2, or ldc(1) out = conf.cmd_and_log([conf.env.D, '--help']) if out.find("D Compiler v") == -1: out = conf.cmd_and_log([conf.env.D, '-version']) if out.find("based on DMD v1.") == -1: conf.fatal("detected compiler is not dmd/ldc") @conf def common_flags_ldc(conf): """ Set the D flags required by *ldc* """ v = conf.env v['DFLAGS'] = ['-d-version=Posix'] v['LINKFLAGS'] = [] v['DFLAGS_dshlib'] = ['-relocation-model=pic'] @conf def common_flags_dmd(conf): """ Set the flags required by *dmd* or *dmd2* """ v = conf.env # _DFLAGS _DIMPORTFLAGS # Compiler is dmd so 'gdc' part will be ignored, just # ensure key is there, so wscript can append flags to it #v['DFLAGS'] = ['-version=Posix'] v['D_SRC_F'] = ['-c'] v['D_TGT_F'] = '-of%s' # linker v['D_LINKER'] = v['D'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-of%s' v['DINC_ST'] = '-I%s' v['DSHLIB_MARKER'] = v['DSTLIB_MARKER'] = '' v['DSTLIB_ST'] = v['DSHLIB_ST'] = '-L-l%s' v['DSTLIBPATH_ST'] = v['DLIBPATH_ST'] = '-L-L%s' v['LINKFLAGS_dprogram']= ['-quiet'] v['DFLAGS_dshlib'] = ['-fPIC'] v['LINKFLAGS_dshlib'] = ['-L-shared'] v['DHEADER_ext'] = '.di' v.DFLAGS_d_with_header = ['-H', '-Hf'] v['D_HDR_F'] = '%s' def configure(conf): """ Configuration for *dmd*, *dmd2*, and *ldc* """ conf.find_dmd() if sys.platform == 'win32': out = conf.cmd_and_log([conf.env.D, '--help']) if out.find("D Compiler v2.") > -1: conf.fatal('dmd2 on Windows is not supported, use gdc or ldc2 instead') conf.load('ar') conf.load('d') conf.common_flags_dmd() conf.d_platform_flags() if str(conf.env.D).find('ldc') > -1: conf.common_flags_ldc() debian/waf-1.7/waflib/Tools/__init__.py0000664000000000000000000000010712145745420014727 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.7/waflib/Tools/ldc2.py0000664000000000000000000000234412145745420014021 0ustar #!/usr/bin/env python # encoding: utf-8 # Alex Rønne Petersen, 2012 (alexrp/Zor) import sys from waflib.Tools import ar, d from waflib.Configure import conf @conf def find_ldc2(conf): """ Find the program *ldc2* and set the variable *D* """ conf.find_program(['ldc2'], var='D') out = conf.cmd_and_log([conf.env.D, '-version']) if out.find("based on DMD v2.") == -1: conf.fatal("detected compiler is not ldc2") @conf def common_flags_ldc2(conf): """ Set the D flags required by *ldc2* """ v = conf.env v['D_SRC_F'] = ['-c'] v['D_TGT_F'] = '-of%s' v['D_LINKER'] = v['D'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-of%s' v['DINC_ST'] = '-I%s' v['DSHLIB_MARKER'] = v['DSTLIB_MARKER'] = '' v['DSTLIB_ST'] = v['DSHLIB_ST'] = '-L-l%s' v['DSTLIBPATH_ST'] = v['DLIBPATH_ST'] = '-L-L%s' v['LINKFLAGS_dshlib'] = ['-L-shared'] v['DHEADER_ext'] = '.di' v['DFLAGS_d_with_header'] = ['-H', '-Hf'] v['D_HDR_F'] = '%s' v['LINKFLAGS'] = [] v['DFLAGS_dshlib'] = ['-relocation-model=pic'] def configure(conf): """ Configuration for *ldc2* """ conf.find_ldc2() conf.load('ar') conf.load('d') conf.common_flags_ldc2() conf.d_platform_flags() debian/waf-1.7/waflib/Tools/c_preproc.py0000664000000000000000000006530712145745420015161 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ C/C++ preprocessor for finding dependencies Reasons for using the Waf preprocessor by default #. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) #. Not all compilers provide .d files for obtaining the dependencies (portability) #. A naive file scanner will not catch the constructs such as "#include foo()" #. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) Regarding the speed concerns: * the preprocessing is performed only when files must be compiled * the macros are evaluated only for #if/#elif/#include * system headers are not scanned by default Now if you do not want the Waf preprocessor, the tool +gccdeps* uses the .d files produced during the compilation to track the dependencies (useful when used with the boost libraries). It only works with gcc >= 4.4 though. A dumb preprocessor is also available in the tool *c_dumbpreproc* """ # TODO: more varargs, pragma once import re, string, traceback from waflib import Logs, Utils, Errors from waflib.Logs import debug, error class PreprocError(Errors.WafError): pass POPFILE = '-' "Constant representing a special token used in :py:meth:`waflib.Tools.c_preproc.c_parser.start` iteration to switch to a header read previously" recursion_limit = 150 "Limit on the amount of files to read in the dependency scanner" go_absolute = False "Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" standard_includes = ['/usr/include'] if Utils.is_win32: standard_includes = [] use_trigraphs = 0 """Apply trigraph rules (False by default)""" strict_quotes = 0 """Reserve the "#include <>" quotes for system includes (do not search for those includes). False by default.""" g_optrans = { 'not':'!', 'and':'&&', 'bitand':'&', 'and_eq':'&=', 'or':'||', 'bitor':'|', 'or_eq':'|=', 'xor':'^', 'xor_eq':'^=', 'compl':'~', } """Operators such as and/or/xor for c++. Set an empty dict to disable.""" # ignore #warning and #error re_lines = re.compile( '^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', re.IGNORECASE | re.MULTILINE) """Match #include lines""" re_mac = re.compile("^[a-zA-Z_]\w*") """Match macro definitions""" re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') """Match macro functions""" re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE) """Match #pragma once statements""" re_nl = re.compile('\\\\\r*\n', re.MULTILINE) """Match newlines""" re_cpp = re.compile( r"""(/\*[^*]*\*+([^/*][^*]*\*+)*/)|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)""", re.MULTILINE) """Filter C/C++ comments""" trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] """Trigraph definitions""" chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} """Escape characters""" NUM = 'i' """Number token""" OP = 'O' """Operator token""" IDENT = 'T' """Identifier token""" STR = 's' """String token""" CHAR = 'c' """Character token""" tok_types = [NUM, STR, IDENT, OP] """Token types""" exp_types = [ r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", r'L?"([^"\\]|\\.)*"', r'[a-zA-Z_]\w*', r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', ] """Expression types""" re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) """Match expressions into tokens""" accepted = 'a' """Parser state is *accepted*""" ignored = 'i' """Parser state is *ignored*, for example preprocessor lines in an #if 0 block""" undefined = 'u' """Parser state is *undefined* at the moment""" skipped = 's' """Parser state is *skipped*, for example preprocessor lines in a #elif 0 block""" def repl(m): """Replace function used with :py:attr:`waflib.Tools.c_preproc.re_cpp`""" s = m.group(1) if s: return ' ' return m.group(3) or '' def filter_comments(filename): """ Filter the comments from a c/h file, and return the preprocessor lines. The regexps :py:attr:`waflib.Tools.c_preproc.re_cpp`, :py:attr:`waflib.Tools.c_preproc.re_nl` and :py:attr:`waflib.Tools.c_preproc.re_lines` are used internally. :return: the preprocessor directives as a list of (keyword, line) :rtype: a list of string pairs """ # return a list of tuples : keyword, line code = Utils.readf(filename) if use_trigraphs: for (a, b) in trig_def: code = code.split(a).join(b) code = re_nl.sub('', code) code = re_cpp.sub(repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_lines, code)] prec = {} """ Operator precendence rules required for parsing expressions of the form:: #if 1 && 2 != 0 """ ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] for x in range(len(ops)): syms = ops[x] for u in syms.split(): prec[u] = x def trimquotes(s): """ Remove the single quotes around an expression:: trimquotes("'test'") == "test" :param s: expression to transform :type s: string :rtype: string """ if not s: return '' s = s.rstrip() if s[0] == "'" and s[-1] == "'": return s[1:-1] return s def reduce_nums(val_1, val_2, val_op): """ Apply arithmetic rules to compute a result :param val1: input parameter :type val1: int or string :param val2: input parameter :type val2: int or string :param val_op: C operator in *+*, */*, *-*, etc :type val_op: string :rtype: int """ #print val_1, val_2, val_op # now perform the operation, make certain a and b are numeric try: a = 0 + val_1 except TypeError: a = int(val_1) try: b = 0 + val_2 except TypeError: b = int(val_2) d = val_op if d == '%': c = a%b elif d=='+': c = a+b elif d=='-': c = a-b elif d=='*': c = a*b elif d=='/': c = a/b elif d=='^': c = a^b elif d=='|': c = a|b elif d=='||': c = int(a or b) elif d=='&': c = a&b elif d=='&&': c = int(a and b) elif d=='==': c = int(a == b) elif d=='!=': c = int(a != b) elif d=='<=': c = int(a <= b) elif d=='<': c = int(a < b) elif d=='>': c = int(a > b) elif d=='>=': c = int(a >= b) elif d=='^': c = int(a^b) elif d=='<<': c = a<>': c = a>>b else: c = 0 return c def get_num(lst): """ Try to obtain a number from a list of tokens. The token types are defined in :py:attr:`waflib.Tools.ccroot.tok_types`. :param lst: list of preprocessor tokens :type lst: list of tuple (tokentype, value) :return: a pair containing the number and the rest of the list :rtype: tuple(value, list) """ if not lst: raise PreprocError("empty list for get_num") (p, v) = lst[0] if p == OP: if v == '(': count_par = 1 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 if count_par == 0: break elif v == '(': count_par += 1 i += 1 else: raise PreprocError("rparen expected %r" % lst) (num, _) = get_term(lst[1:i]) return (num, lst[i+1:]) elif v == '+': return get_num(lst[1:]) elif v == '-': num, lst = get_num(lst[1:]) return (reduce_nums('-1', num, '*'), lst) elif v == '!': num, lst = get_num(lst[1:]) return (int(not int(num)), lst) elif v == '~': num, lst = get_num(lst[1:]) return (~ int(num), lst) else: raise PreprocError("Invalid op token %r for get_num" % lst) elif p == NUM: return v, lst[1:] elif p == IDENT: # all macros should have been replaced, remaining identifiers eval to 0 return 0, lst[1:] else: raise PreprocError("Invalid token %r for get_num" % lst) def get_term(lst): """ Evaluate an expression recursively, for example:: 1+1+1 -> 2+1 -> 3 :param lst: list of tokens :type lst: list of tuple(token, value) :return: the value and the remaining tokens :rtype: value, list """ if not lst: raise PreprocError("empty list for get_term") num, lst = get_num(lst) if not lst: return (num, []) (p, v) = lst[0] if p == OP: if v == ',': # skip return get_term(lst[1:]) elif v == '?': count_par = 0 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 elif v == '(': count_par += 1 elif v == ':': if count_par == 0: break i += 1 else: raise PreprocError("rparen expected %r" % lst) if int(num): return get_term(lst[1:i]) else: return get_term(lst[i+1:]) else: num2, lst = get_num(lst[1:]) if not lst: # no more tokens to process num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) # operator precedence p2, v2 = lst[0] if p2 != OP: raise PreprocError("op expected %r" % lst) if prec[v2] >= prec[v]: num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) else: num3, lst = get_num(lst[1:]) num3 = reduce_nums(num2, num3, v2) return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) raise PreprocError("cannot reduce %r" % lst) def reduce_eval(lst): """ Take a list of tokens and output true or false for #if/#elif conditions. :param lst: a list of tokens :type lst: list of tuple(token, value) :return: a token :rtype: tuple(NUM, int) """ num, lst = get_term(lst) return (NUM, num) def stringize(lst): """ Merge a list of tokens into a string :param lst: a list of tokens :type lst: list of tuple(token, value) :rtype: string """ lst = [str(v2) for (p2, v2) in lst] return "".join(lst) def paste_tokens(t1, t2): """ Token pasting works between identifiers, particular operators, and identifiers and numbers:: a ## b -> ab > ## = -> >= a ## 2 -> a2 :param t1: token :type t1: tuple(type, value) :param t2: token :type t2: tuple(type, value) """ p1 = None if t1[0] == OP and t2[0] == OP: p1 = OP elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): p1 = IDENT elif t1[0] == NUM and t2[0] == NUM: p1 = NUM if not p1: raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) return (p1, t1[1] + t2[1]) def reduce_tokens(lst, defs, ban=[]): """ Replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :param ban: macros that cannot be substituted (recursion is not allowed) :type ban: list of string :return: the new list of tokens :rtype: value, list """ i = 0 while i < len(lst): (p, v) = lst[i] if p == IDENT and v == "defined": del lst[i] if i < len(lst): (p2, v2) = lst[i] if p2 == IDENT: if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) elif p2 == OP and v2 == '(': del lst[i] (p2, v2) = lst[i] del lst[i] # remove the ident, and change the ) for the value if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) else: raise PreprocError("Invalid define expression %r" % lst) elif p == IDENT and v in defs: if isinstance(defs[v], str): a, b = extract_macro(defs[v]) defs[v] = b macro_def = defs[v] to_add = macro_def[1] if isinstance(macro_def[0], list): # macro without arguments del lst[i] accu = to_add[:] reduce_tokens(accu, defs, ban+[v]) for x in range(len(accu)): lst.insert(i, accu[x]) i += 1 else: # collect the arguments for the funcall args = [] del lst[i] if i >= len(lst): raise PreprocError("expected '(' after %r (got nothing)" % v) (p2, v2) = lst[i] if p2 != OP or v2 != '(': raise PreprocError("expected '(' after %r" % v) del lst[i] one_param = [] count_paren = 0 while i < len(lst): p2, v2 = lst[i] del lst[i] if p2 == OP and count_paren == 0: if v2 == '(': one_param.append((p2, v2)) count_paren += 1 elif v2 == ')': if one_param: args.append(one_param) break elif v2 == ',': if not one_param: raise PreprocError("empty param in funcall %s" % p) args.append(one_param) one_param = [] else: one_param.append((p2, v2)) else: one_param.append((p2, v2)) if v2 == '(': count_paren += 1 elif v2 == ')': count_paren -= 1 else: raise PreprocError('malformed macro') # substitute the arguments within the define expression accu = [] arg_table = macro_def[0] j = 0 while j < len(to_add): (p2, v2) = to_add[j] if p2 == OP and v2 == '#': # stringize is for arguments only if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] accu.append((STR, stringize(toks))) j += 1 else: accu.append((p2, v2)) elif p2 == OP and v2 == '##': # token pasting, how can man invent such a complicated system? if accu and j+1 < len(to_add): # we have at least two tokens t1 = accu[-1] if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] if toks: accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) accu.extend(toks[1:]) else: # error, case "a##" accu.append((p2, v2)) accu.extend(toks) elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': # TODO not sure # first collect the tokens va_toks = [] st = len(macro_def[0]) pt = len(args) for x in args[pt-st+1:]: va_toks.extend(x) va_toks.append((OP, ',')) if va_toks: va_toks.pop() # extra comma if len(accu)>1: (p3, v3) = accu[-1] (p4, v4) = accu[-2] if v3 == '##': # remove the token paste accu.pop() if v4 == ',' and pt < st: # remove the comma accu.pop() accu += va_toks else: accu[-1] = paste_tokens(t1, to_add[j+1]) j += 1 else: # Invalid paste, case "##a" or "b##" accu.append((p2, v2)) elif p2 == IDENT and v2 in arg_table: toks = args[arg_table[v2]] reduce_tokens(toks, defs, ban+[v]) accu.extend(toks) else: accu.append((p2, v2)) j += 1 reduce_tokens(accu, defs, ban+[v]) for x in range(len(accu)-1, -1, -1): lst.insert(i, accu[x]) i += 1 def eval_macro(lst, defs): """ Reduce the tokens by :py:func:`waflib.Tools.c_preproc.reduce_tokens` and try to return a 0/1 result by :py:func:`waflib.Tools.c_preproc.reduce_eval`. :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :rtype: int """ reduce_tokens(lst, defs, []) if not lst: raise PreprocError("missing tokens to evaluate") (p, v) = reduce_eval(lst) return int(v) != 0 def extract_macro(txt): """ Process a macro definition of the form:: #define f(x, y) x * y into a function or a simple macro without arguments :param txt: expression to exact a macro definition from :type txt: string :return: a tuple containing the name, the list of arguments and the replacement :rtype: tuple(string, [list, list]) """ t = tokenize(txt) if re_fun.search(txt): p, name = t[0] p, v = t[1] if p != OP: raise PreprocError("expected open parenthesis") i = 1 pindex = 0 params = {} prev = '(' while 1: i += 1 p, v = t[i] if prev == '(': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == ')': break else: raise PreprocError("unexpected token (3)") elif prev == IDENT: if p == OP and v == ',': prev = v elif p == OP and v == ')': break else: raise PreprocError("comma or ... expected") elif prev == ',': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == '...': raise PreprocError("not implemented (1)") else: raise PreprocError("comma or ... expected (2)") elif prev == '...': raise PreprocError("not implemented (2)") else: raise PreprocError("unexpected else") #~ print (name, [params, t[i+1:]]) return (name, [params, t[i+1:]]) else: (p, v) = t[0] return (v, [[], t[1:]]) re_include = re.compile('^\s*(<(?P.*)>|"(?P.*)")') def extract_include(txt, defs): """ Process a line in the form:: #include foo :param txt: include line to process :type txt: string :param defs: macro definitions :type defs: dict :return: the file name :rtype: string """ m = re_include.search(txt) if m: if m.group('a'): return '<', m.group('a') if m.group('b'): return '"', m.group('b') # perform preprocessing and look at the result, it must match an include toks = tokenize(txt) reduce_tokens(toks, defs, ['waf_include']) if not toks: raise PreprocError("could not parse include %s" % txt) if len(toks) == 1: if toks[0][0] == STR: return '"', toks[0][1] else: if toks[0][1] == '<' and toks[-1][1] == '>': return stringize(toks).lstrip('<').rstrip('>') raise PreprocError("could not parse include %s." % txt) def parse_char(txt): """ Parse a c character :param txt: character to parse :type txt: string :return: a character literal :rtype: string """ if not txt: raise PreprocError("attempted to parse a null char") if txt[0] != '\\': return ord(txt) c = txt[1] if c == 'x': if len(txt) == 4 and txt[3] in string.hexdigits: return int(txt[2:], 16) return int(txt[2:], 16) elif c.isdigit(): if c == '0' and len(txt)==2: return 0 for i in 3, 2, 1: if len(txt) > i and txt[1:1+i].isdigit(): return (1+i, int(txt[1:1+i], 8)) else: try: return chr_esc[c] except KeyError: raise PreprocError("could not parse char literal '%s'" % txt) def tokenize(s): """ Convert a string into a list of tokens (shlex.split does not apply to c/c++/d) :param s: input to tokenize :type s: string :return: a list of tokens :rtype: list of tuple(token, value) """ return tokenize_private(s)[:] # force a copy of the results @Utils.run_once def tokenize_private(s): ret = [] for match in re_clexer.finditer(s): m = match.group for name in tok_types: v = m(name) if v: if name == IDENT: try: v = g_optrans[v]; name = OP except KeyError: # c++ specific if v.lower() == "true": v = 1 name = NUM elif v.lower() == "false": v = 0 name = NUM elif name == NUM: if m('oct'): v = int(v, 8) elif m('hex'): v = int(m('hex'), 16) elif m('n0'): v = m('n0') else: v = m('char') if v: v = parse_char(v) else: v = m('n2') or m('n4') elif name == OP: if v == '%:': v = '#' elif v == '%:%:': v = '##' elif name == STR: # remove the quotes around the string v = v[1:-1] ret.append((name, v)) break return ret @Utils.run_once def define_name(line): """ :param line: define line :type line: string :rtype: string :return: the define name """ return re_mac.match(line).group(0) class c_parser(object): """ Used by :py:func:`waflib.Tools.c_preproc.scan` to parse c/h files. Note that by default, only project headers are parsed. """ def __init__(self, nodepaths=None, defines=None): self.lines = [] """list of lines read""" if defines is None: self.defs = {} else: self.defs = dict(defines) # make a copy self.state = [] self.count_files = 0 self.currentnode_stack = [] self.nodepaths = nodepaths or [] """Include paths""" self.nodes = [] """List of :py:class:`waflib.Node.Node` found so far""" self.names = [] """List of file names that could not be matched by any file""" self.curfile = '' """Current file""" self.ban_includes = set([]) """Includes that must not be read (#pragma once)""" def cached_find_resource(self, node, filename): """ Find a file from the input directory :param node: directory :type node: :py:class:`waflib.Node.Node` :param filename: header to find :type filename: string :return: the node if found, or None :rtype: :py:class:`waflib.Node.Node` """ try: nd = node.ctx.cache_nd except AttributeError: nd = node.ctx.cache_nd = {} tup = (node, filename) try: return nd[tup] except KeyError: ret = node.find_resource(filename) if ret: if getattr(ret, 'children', None): ret = None elif ret.is_child_of(node.ctx.bldnode): tmp = node.ctx.srcnode.search_node(ret.path_from(node.ctx.bldnode)) if tmp and getattr(tmp, 'children', None): ret = None nd[tup] = ret return ret def tryfind(self, filename): """ Try to obtain a node from the filename based from the include paths. Will add the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to :py:attr:`waflib.Tools.c_preproc.c_parser.names` if no corresponding file is found. Called by :py:attr:`waflib.Tools.c_preproc.c_parser.start`. :param filename: header to find :type filename: string :return: the node if found :rtype: :py:class:`waflib.Node.Node` """ self.curfile = filename # for msvc it should be a for loop on the whole stack found = self.cached_find_resource(self.currentnode_stack[-1], filename) for n in self.nodepaths: if found: break found = self.cached_find_resource(n, filename) if found and not found in self.ban_includes: # TODO the duplicates do not increase the no-op build times too much, but they may be worth removing self.nodes.append(found) if filename[-4:] != '.moc': self.addlines(found) else: if not filename in self.names: self.names.append(filename) return found def addlines(self, node): """ Add the lines from a header in the list of preprocessor lines to parse :param node: header :type node: :py:class:`waflib.Node.Node` """ self.currentnode_stack.append(node.parent) filepath = node.abspath() self.count_files += 1 if self.count_files > recursion_limit: # issue #812 raise PreprocError("recursion limit exceeded") pc = self.parse_cache debug('preproc: reading file %r', filepath) try: lns = pc[filepath] except KeyError: pass else: self.lines.extend(lns) return try: lines = filter_comments(filepath) lines.append((POPFILE, '')) lines.reverse() pc[filepath] = lines # cache the lines filtered self.lines.extend(lines) except IOError: raise PreprocError("could not read the file %s" % filepath) except Exception: if Logs.verbose > 0: error("parsing %s failed" % filepath) traceback.print_exc() def start(self, node, env): """ Preprocess a source file to obtain the dependencies, which are accumulated to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` and :py:attr:`waflib.Tools.c_preproc.c_parser.names`. :param node: source file :type node: :py:class:`waflib.Node.Node` :param env: config set containing additional defines to take into account :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ debug('preproc: scanning %s (in %s)', node.name, node.parent.name) bld = node.ctx try: self.parse_cache = bld.parse_cache except AttributeError: bld.parse_cache = {} self.parse_cache = bld.parse_cache self.current_file = node self.addlines(node) # macros may be defined on the command-line, so they must be parsed as if they were part of the file if env['DEFINES']: try: lst = ['%s %s' % (x[0], trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in env['DEFINES']]] lst.reverse() self.lines.extend([('define', x) for x in lst]) except AttributeError: # if the defines are invalid the compiler will tell the user pass while self.lines: (token, line) = self.lines.pop() if token == POPFILE: self.count_files -= 1 self.currentnode_stack.pop() continue try: ve = Logs.verbose if ve: debug('preproc: line is %s - %s state is %s', token, line, self.state) state = self.state # make certain we define the state if we are about to enter in an if block if token[:2] == 'if': state.append(undefined) elif token == 'endif': state.pop() # skip lines when in a dead 'if' branch, wait for the endif if token[0] != 'e': if skipped in self.state or ignored in self.state: continue if token == 'if': ret = eval_macro(tokenize(line), self.defs) if ret: state[-1] = accepted else: state[-1] = ignored elif token == 'ifdef': m = re_mac.match(line) if m and m.group(0) in self.defs: state[-1] = accepted else: state[-1] = ignored elif token == 'ifndef': m = re_mac.match(line) if m and m.group(0) in self.defs: state[-1] = ignored else: state[-1] = accepted elif token == 'include' or token == 'import': (kind, inc) = extract_include(line, self.defs) if ve: debug('preproc: include found %s (%s) ', inc, kind) if kind == '"' or not strict_quotes: self.current_file = self.tryfind(inc) if token == 'import': self.ban_includes.add(self.current_file) elif token == 'elif': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: if eval_macro(tokenize(line), self.defs): state[-1] = accepted elif token == 'else': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: state[-1] = accepted elif token == 'define': try: self.defs[define_name(line)] = line except Exception: raise PreprocError("Invalid define line %s" % line) elif token == 'undef': m = re_mac.match(line) if m and m.group(0) in self.defs: self.defs.__delitem__(m.group(0)) #print "undef %s" % name elif token == 'pragma': if re_pragma_once.match(line.lower()): self.ban_includes.add(self.current_file) except Exception as e: if Logs.verbose: debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack()) def scan(task): """ Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind:: #include some_macro() This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example """ global go_absolute try: incn = task.generator.includes_nodes except AttributeError: raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": ' % task.generator) if go_absolute: nodepaths = incn + [task.generator.bld.root.find_dir(x) for x in standard_includes] else: nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] tmp = c_parser(nodepaths) tmp.start(task.inputs[0], task.env) if Logs.verbose: debug('deps: deps for %r: %r; unresolved %r' % (task.inputs, tmp.nodes, tmp.names)) return (tmp.nodes, tmp.names) debian/waf-1.7/waflib/Tools/asm.py0000664000000000000000000000321012145745420013746 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Assembly support, used by tools such as gas and nasm To declare targets using assembly:: def configure(conf): conf.load('gcc gas') def build(bld): bld( features='c cstlib asm', source = 'test.S', target = 'asmtest') bld( features='asm asmprogram', source = 'test.S', target = 'asmtest') Support for pure asm programs and libraries should also work:: def configure(conf): conf.load('nasm') conf.find_program('ld', 'ASLINK') def build(bld): bld( features='asm asmprogram', source = 'test.S', target = 'asmtest') """ import os, sys from waflib import Task, Utils import waflib.Task from waflib.Tools.ccroot import link_task, stlink_task from waflib.TaskGen import extension, feature class asm(Task.Task): """ Compile asm files by gas/nasm/yasm/... """ color = 'BLUE' run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' @extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') def asm_hook(self, node): """ Bind the asm extension to the asm task :param node: input file :type node: :py:class:`waflib.Node.Node` """ return self.create_compiled_task('asm', node) class asmprogram(link_task): "Link object files into a c program" run_str = '${ASLINK} ${ASLINKFLAGS} ${ASLNK_TGT_F}${TGT} ${ASLNK_SRC_F}${SRC}' ext_out = ['.bin'] inst_to = '${BINDIR}' class asmshlib(asmprogram): "Link object files into a c shared library" inst_to = '${LIBDIR}' class asmstlib(stlink_task): "Link object files into a c static library" pass # do not remove def configure(conf): conf.env['ASMPATH_ST'] = '-I%s' debian/waf-1.7/waflib/Tools/compiler_d.py0000664000000000000000000000304612145745420015312 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2010 (ita) """ Try to detect a D compiler from the list of supported compilers:: def options(opt): opt.load('compiler_d') def configure(cnf): cnf.load('compiler_d') def build(bld): bld.program(source='main.d', target='app') Only three D compilers are really present at the moment: * gdc * dmd, the ldc compiler having a very similar command-line interface * ldc2 """ import os, sys, imp, types from waflib import Utils, Configure, Options, Logs def configure(conf): """ Try to find a suitable D compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ for compiler in conf.options.dcheck.split(','): conf.env.stash() conf.start_msg('Checking for %r (d compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_d: %r' % e) else: if conf.env.D: conf.end_msg(conf.env.get_flat('D')) conf.env['COMPILER_D'] = compiler break conf.end_msg(False) else: conf.fatal('no suitable d compiler was found') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-d-compiler=dmd """ d_compiler_opts = opt.add_option_group('D Compiler Options') d_compiler_opts.add_option('--check-d-compiler', default='gdc,dmd,ldc2', action='store', help='check for the compiler [Default:gdc,dmd,ldc2]', dest='dcheck') for d_compiler in ['gdc', 'dmd', 'ldc2']: opt.load('%s' % d_compiler) debian/waf-1.7/waflib/Tools/compiler_fc.py0000664000000000000000000000401312145745420015452 0ustar #!/usr/bin/env python # encoding: utf-8 import os, sys, imp, types from waflib import Utils, Configure, Options, Logs, Errors from waflib.Tools import fc fc_compiler = { 'win32' : ['gfortran','ifort'], 'darwin' : ['gfortran', 'g95', 'ifort'], 'linux' : ['gfortran', 'g95', 'ifort'], 'java' : ['gfortran', 'g95', 'ifort'], 'default': ['gfortran'], 'aix' : ['gfortran'] } def __list_possible_compiler(platform): try: return fc_compiler[platform] except KeyError: return fc_compiler["default"] def configure(conf): """ Try to find a suitable Fortran compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_fc except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_fc')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (fortran compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_fortran: %r' % e) else: if conf.env['FC']: conf.end_msg(conf.env.get_flat('FC')) conf.env.COMPILER_FORTRAN = compiler break conf.end_msg(False) else: conf.fatal('could not configure a fortran compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-fortran-compiler=ifort """ opt.load_special_tools('fc_*.py') build_platform = Utils.unversioned_sys_platform() detected_platform = Options.platform possible_compiler_list = __list_possible_compiler(detected_platform) test_for_compiler = ' '.join(possible_compiler_list) fortran_compiler_opts = opt.add_option_group("Fortran Compiler Options") fortran_compiler_opts.add_option('--check-fortran-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following Fortran Compiler will be checked by default: "%s"' % (detected_platform, test_for_compiler), dest="check_fc") for compiler in test_for_compiler.split(): opt.load('%s' % compiler) debian/waf-1.7/waflib/Tools/errcheck.py0000664000000000000000000001537312145745420014771 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ errcheck: highlight common mistakes There is a performance hit, so this tool is only loaded when running "waf -v" """ typos = { 'feature':'features', 'sources':'source', 'targets':'target', 'include':'includes', 'export_include':'export_includes', 'define':'defines', 'importpath':'includes', 'installpath':'install_path', 'iscopy':'is_copy', } meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils import waflib.Tools.ccroot def check_same_targets(self): mp = Utils.defaultdict(list) uids = {} def check_task(tsk): if not isinstance(tsk, Task.Task): return for node in tsk.outputs: mp[node].append(tsk) try: uids[tsk.uid()].append(tsk) except KeyError: uids[tsk.uid()] = [tsk] for g in self.groups: for tg in g: try: for tsk in tg.tasks: check_task(tsk) except AttributeError: # raised if not a task generator, which should be uncommon check_task(tg) dupe = False for (k, v) in mp.items(): if len(v) > 1: dupe = True msg = '* Node %r is created more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "") Logs.error(msg) for x in v: if Logs.verbose > 1: Logs.error(' %d. %r' % (1 + v.index(x), x.generator)) else: Logs.error(' %d. %r in %r' % (1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None))) if not dupe: for (k, v) in uids.items(): if len(v) > 1: Logs.error('* Several tasks use the same identifier. Please check the information on\n http://docs.waf.googlecode.com/git/apidocs_16/Task.html#waflib.Task.Task.uid') for tsk in v: Logs.error(' - object %r (%r) defined in %r' % (tsk.__class__.__name__, tsk, tsk.generator)) def check_invalid_constraints(self): feat = set([]) for x in list(TaskGen.feats.values()): feat.union(set(x)) for (x, y) in TaskGen.task_gen.prec.items(): feat.add(x) feat.union(set(y)) ext = set([]) for x in TaskGen.task_gen.mappings.values(): ext.add(x.__name__) invalid = ext & feat if invalid: Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method' % list(invalid)) # the build scripts have been read, so we can check for invalid after/before attributes on task classes for cls in list(Task.classes.values()): for x in ('before', 'after'): for y in Utils.to_list(getattr(cls, x, [])): if not Task.classes.get(y, None): Logs.error('Erroneous order constraint %r=%r on task class %r' % (x, y, cls.__name__)) if getattr(cls, 'rule', None): Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")' % cls.__name__) def replace(m): """ We could add properties, but they would not work in some cases: bld.program(...) requires 'source' in the attributes """ oldcall = getattr(Build.BuildContext, m) def call(self, *k, **kw): ret = oldcall(self, *k, **kw) for x in typos: if x in kw: if x == 'iscopy' and 'subst' in getattr(self, 'features', ''): continue err = True Logs.error('Fix the typo %r -> %r on %r' % (x, typos[x], ret)) return ret setattr(Build.BuildContext, m, call) def enhance_lib(): """ modify existing classes and methods """ for m in meths_typos: replace(m) # catch '..' in ant_glob patterns def ant_glob(self, *k, **kw): if k: lst=Utils.to_list(k[0]) for pat in lst: if '..' in pat.split('/'): Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'" % k[0]) if kw.get('remove', True): try: if self.is_child_of(self.ctx.bldnode) and not kw.get('quiet', False): Logs.error('Using ant_glob on the build folder (%r) is dangerous (quiet=True to disable this warning)' % self) except AttributeError: pass return self.old_ant_glob(*k, **kw) Node.Node.old_ant_glob = Node.Node.ant_glob Node.Node.ant_glob = ant_glob # catch conflicting ext_in/ext_out/before/after declarations old = Task.is_before def is_before(t1, t2): ret = old(t1, t2) if ret and old(t2, t1): Logs.error('Contradictory order constraints in classes %r %r' % (t1, t2)) return ret Task.is_before = is_before # check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose # so we only issue a warning def check_err_features(self): lst = self.to_list(self.features) if 'shlib' in lst: Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') for x in ('c', 'cxx', 'd', 'fc'): if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]: Logs.error('%r features is probably missing %r' % (self, x)) TaskGen.feature('*')(check_err_features) # check for erroneous order constraints def check_err_order(self): if not hasattr(self, 'rule') and not 'subst' in Utils.to_list(self.features): for x in ('before', 'after', 'ext_in', 'ext_out'): if hasattr(self, x): Logs.warn('Erroneous order constraint %r on non-rule based task generator %r' % (x, self)) else: for x in ('before', 'after'): for y in self.to_list(getattr(self, x, [])): if not Task.classes.get(y, None): Logs.error('Erroneous order constraint %s=%r on %r (no such class)' % (x, y, self)) TaskGen.feature('*')(check_err_order) # check for @extension used with @feature/@before_method/@after_method def check_compile(self): check_invalid_constraints(self) try: ret = self.orig_compile() finally: check_same_targets(self) return ret Build.BuildContext.orig_compile = Build.BuildContext.compile Build.BuildContext.compile = check_compile # check for invalid build groups #914 def use_rec(self, name, **kw): try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: pass else: idx = self.bld.get_group_idx(self) odx = self.bld.get_group_idx(y) if odx > idx: msg = "Invalid 'use' across build groups:" if Logs.verbose > 1: msg += '\n target %r\n uses:\n %r' % (self, y) else: msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name) raise Errors.WafError(msg) self.orig_use_rec(name, **kw) TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec TaskGen.task_gen.use_rec = use_rec # check for env.append def getattri(self, name, default=None): if name == 'append' or name == 'add': raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') elif name == 'prepend': raise Errors.WafError('env.prepend does not exist: use env.prepend_value') if name in self.__slots__: return object.__getattr__(self, name, default) else: return self[name] ConfigSet.ConfigSet.__getattr__ = getattri def options(opt): """ Add a few methods """ enhance_lib() def configure(conf): pass debian/waf-1.7/waflib/Tools/c_osx.py0000664000000000000000000001261512145745420014312 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2008-2010 """ MacOSX related tools """ import os, shutil, sys, platform from waflib import TaskGen, Task, Build, Options, Utils, Errors from waflib.TaskGen import taskgen_method, feature, after_method, before_method app_info = ''' CFBundlePackageType APPL CFBundleGetInfoString Created by Waf CFBundleSignature ???? NOTE THIS IS A GENERATED FILE, DO NOT MODIFY CFBundleExecutable %s ''' """ plist template """ @feature('c', 'cxx') def set_macosx_deployment_target(self): """ see WAF issue 285 and also and also http://trac.macports.org/ticket/17059 """ if self.env['MACOSX_DEPLOYMENT_TARGET']: os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env['MACOSX_DEPLOYMENT_TARGET'] elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: if Utils.unversioned_sys_platform() == 'darwin': os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) @taskgen_method def create_bundle_dirs(self, name, out): """ Create bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp` """ bld = self.bld dir = out.parent.find_or_declare(name) dir.mkdir() macos = dir.find_or_declare(['Contents', 'MacOS']) macos.mkdir() return dir def bundle_name_for_output(out): name = out.name k = name.rfind('.') if k >= 0: name = name[:k] + '.app' else: name = name + '.app' return name @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macapp(self): """ To compile an executable into a Mac application (a .app), set its *mac_app* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_app = True) To force *all* executables to be transformed into Mac applications:: def build(bld): bld.env.MACAPP = True bld.shlib(source='a.c', target='foo') """ if self.env['MACAPP'] or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) self.apptask = self.create_task('macapp', self.link_task.outputs, n1) inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name self.bld.install_files(inst_to, n1, chmod=Utils.O755) if getattr(self, 'mac_resources', None): res_dir = n1.parent.parent.make_node('Resources') inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name for x in self.to_list(self.mac_resources): node = self.path.find_node(x) if not node: raise Errors.WafError('Missing mac_resource %r in %r' % (x, self)) parent = node.parent if os.path.isdir(node.abspath()): nodes = node.ant_glob('**') else: nodes = [node] for node in nodes: rel = node.path_from(parent) tsk = self.create_task('macapp', node, res_dir.make_node(rel)) self.bld.install_as(inst_to + '/%s' % rel, node) if getattr(self.bld, 'is_install', None): # disable the normal binary installation self.install_task.hasrun = Task.SKIP_ME @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macplist(self): """ Create a :py:class:`waflib.Tools.c_osx.macplist` instance. """ if self.env['MACAPP'] or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'Info.plist']) self.plisttask = plisttask = self.create_task('macplist', [], n1) if getattr(self, 'mac_plist', False): node = self.path.find_resource(self.mac_plist) if node: plisttask.inputs.append(node) else: plisttask.code = self.mac_plist else: plisttask.code = app_info % self.link_task.outputs[0].name inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name self.bld.install_files(inst_to, n1) @feature('cshlib', 'cxxshlib') @before_method('apply_link', 'propagate_uselib_vars') def apply_bundle(self): """ To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_bundle = True) To force *all* executables to be transformed into bundles:: def build(bld): bld.env.MACBUNDLE = True bld.shlib(source='a.c', target='foo') """ if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False): self.env['LINKFLAGS_cshlib'] = self.env['LINKFLAGS_cxxshlib'] = [] # disable the '-dynamiclib' flag self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['macbundle_PATTERN'] use = self.use = self.to_list(getattr(self, 'use', [])) if not 'MACBUNDLE' in use: use.append('MACBUNDLE') app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] class macapp(Task.Task): """ Create mac applications """ color = 'PINK' def run(self): self.outputs[0].parent.mkdir() shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath()) class macplist(Task.Task): """ Create plist files """ color = 'PINK' ext_in = ['.bin'] def run(self): if getattr(self, 'code', None): txt = self.code else: txt = self.inputs[0].read() self.outputs[0].write(txt) debian/waf-1.7/waflib/Tools/irixcc.py0000664000000000000000000000265312145745420014461 0ustar #! /usr/bin/env python # imported from samba """ compiler definition for irix/MIPSpro cc compiler based on suncc.py from waf """ import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_irixcc(conf): v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('cc', var='CC') if not cc: conf.fatal('irixcc was not found') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-version']) except Exception: conf.fatal('%r -version could not be executed' % cc) v['CC'] = cc v['CC_NAME'] = 'irix' @conf def irixcc_common_flags(conf): v = conf.env v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o'] v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['cprogram_PATTERN'] = '%s' v['cshlib_PATTERN'] = 'lib%s.so' v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_irixcc() conf.find_cpp() conf.find_ar() conf.irixcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/javaw.py0000664000000000000000000003147312145745420014312 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Java support Javac is one of the few compilers that behaves very badly: #. it outputs files where it wants to (-d is only for the package root) #. it recompiles files silently behind your back #. it outputs an undefined amount of files (inner classes) Remember that the compilation can be performed using Jython[1] rather than regular Python. Instead of running one of the following commands:: ./waf configure python waf configure You would have to run:: java -jar /path/to/jython.jar waf configure [1] http://www.jython.org/ """ import os, re, tempfile, shutil from waflib import TaskGen, Task, Utils, Options, Build, Errors, Node, Logs from waflib.Configure import conf from waflib.TaskGen import feature, before_method, after_method from waflib.Tools import ccroot ccroot.USELIB_VARS['javac'] = set(['CLASSPATH', 'JAVACFLAGS']) SOURCE_RE = '**/*.java' JAR_RE = '**/*' class_check_source = ''' public class Test { public static void main(String[] argv) { Class lib; if (argv.length < 1) { System.err.println("Missing argument"); System.exit(77); } try { lib = Class.forName(argv[0]); } catch (ClassNotFoundException e) { System.err.println("ClassNotFoundException"); System.exit(1); } lib = null; System.exit(0); } } ''' @feature('javac') @before_method('process_source') def apply_java(self): """ Create a javac task for compiling *.java files*. There can be only one javac task by task generator. """ Utils.def_attrs(self, jarname='', classpath='', sourcepath='.', srcdir='.', jar_mf_attributes={}, jar_mf_classpath=[]) nodes_lst = [] outdir = getattr(self, 'outdir', None) if outdir: if not isinstance(outdir, Node.Node): outdir = self.path.get_bld().make_node(self.outdir) else: outdir = self.path.get_bld() outdir.mkdir() self.outdir = outdir self.env['OUTDIR'] = outdir.abspath() self.javac_task = tsk = self.create_task('javac') tmp = [] srcdir = getattr(self, 'srcdir', '') if isinstance(srcdir, Node.Node): srcdir = [srcdir] for x in Utils.to_list(srcdir): if isinstance(x, Node.Node): y = x else: y = self.path.find_dir(x) if not y: self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) tmp.append(y) tsk.srcdir = tmp if getattr(self, 'compat', None): tsk.env.append_value('JAVACFLAGS', ['-source', self.compat]) if hasattr(self, 'sourcepath'): fold = [isinstance(x, Node.Node) and x or self.path.find_dir(x) for x in self.to_list(self.sourcepath)] names = os.pathsep.join([x.srcpath() for x in fold]) else: names = [x.srcpath() for x in tsk.srcdir] if names: tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) @feature('javac') @after_method('apply_java') def use_javac_files(self): """ Process the *use* attribute referring to other java compilations """ lst = [] self.uselib = self.to_list(getattr(self, 'uselib', [])) names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except Exception: self.uselib.append(x) else: y.post() lst.append(y.jar_task.outputs[0].abspath()) self.javac_task.set_run_after(y.jar_task) if lst: self.env.append_value('CLASSPATH', lst) @feature('javac') @after_method('apply_java', 'propagate_uselib_vars', 'use_javac_files') def set_classpath(self): """ Set the CLASSPATH value on the *javac* task previously created. """ self.env.append_value('CLASSPATH', getattr(self, 'classpath', [])) for x in self.tasks: x.env.CLASSPATH = os.pathsep.join(self.env.CLASSPATH) + os.pathsep @feature('jar') @after_method('apply_java', 'use_javac_files') @before_method('process_source') def jar_files(self): """ Create a jar task. There can be only one jar task by task generator. """ destfile = getattr(self, 'destfile', 'test.jar') jaropts = getattr(self, 'jaropts', []) manifest = getattr(self, 'manifest', None) basedir = getattr(self, 'basedir', None) if basedir: if not isinstance(self.basedir, Node.Node): basedir = self.path.get_bld().make_node(basedir) else: basedir = self.path.get_bld() if not basedir: self.bld.fatal('Could not find the basedir %r for %r' % (self.basedir, self)) self.jar_task = tsk = self.create_task('jar_create') if manifest: jarcreate = getattr(self, 'jarcreate', 'cfm') node = self.path.find_node(manifest) tsk.dep_nodes.append(node) jaropts.insert(0, node.abspath()) else: jarcreate = getattr(self, 'jarcreate', 'cf') if not isinstance(destfile, Node.Node): destfile = self.path.find_or_declare(destfile) if not destfile: self.bld.fatal('invalid destfile %r for %r' % (destfile, self)) tsk.set_outputs(destfile) tsk.basedir = basedir jaropts.append('-C') jaropts.append(basedir.bldpath()) jaropts.append('.') tsk.env['JAROPTS'] = jaropts tsk.env['JARCREATE'] = jarcreate if getattr(self, 'javac_task', None): tsk.set_run_after(self.javac_task) @feature('jar') @after_method('jar_files') def use_jar_files(self): """ Process the *use* attribute to set the build order on the tasks created by another task generator. """ lst = [] self.uselib = self.to_list(getattr(self, 'uselib', [])) names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except Exception: self.uselib.append(x) else: y.post() self.jar_task.run_after.update(y.tasks) class jar_create(Task.Task): """ Create a jar file """ color = 'GREEN' run_str = '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' def runnable_status(self): """ Wait for dependent tasks to be executed, then read the files to update the list of inputs. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global JAR_RE try: self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False) if id(x) != id(self.outputs[0])] except Exception: raise Errors.WafError('Could not find the basedir %r for %r' % (self.basedir, self)) return super(jar_create, self).runnable_status() class javac(Task.Task): """ Compile java files """ color = 'BLUE' nocache = True """ The .class files cannot be put into a cache at the moment """ vars = ['CLASSPATH', 'JAVACFLAGS', 'JAVAC', 'OUTDIR'] """ The javac task will be executed again if the variables CLASSPATH, JAVACFLAGS, JAVAC or OUTDIR change. """ def runnable_status(self): """ Wait for dependent tasks to be complete, then read the file system to find the input nodes. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global SOURCE_RE self.inputs = [] for x in self.srcdir: self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) return super(javac, self).runnable_status() def run(self): """ Execute the javac compiler """ env = self.env gen = self.generator bld = gen.bld wd = bld.bldnode.abspath() def to_list(xx): if isinstance(xx, str): return [xx] return xx cmd = [] cmd.extend(to_list(env['JAVAC'])) cmd.extend(['-classpath']) cmd.extend(to_list(env['CLASSPATH'])) cmd.extend(['-d']) cmd.extend(to_list(env['OUTDIR'])) cmd.extend(to_list(env['JAVACFLAGS'])) files = [a.path_from(bld.bldnode) for a in self.inputs] # workaround for command line length limit: # http://support.microsoft.com/kb/830473 tmp = None try: if len(str(files)) + len(str(cmd)) > 8192: (fd, tmp) = tempfile.mkstemp(dir=bld.bldnode.abspath()) try: os.write(fd, '\n'.join(files).encode()) finally: if tmp: os.close(fd) if Logs.verbose: Logs.debug('runner: %r' % (cmd + files)) cmd.append('@' + tmp) else: cmd += files ret = self.exec_command(cmd, cwd=wd, env=env.env or None) finally: if tmp: os.unlink(tmp) return ret def post_run(self): """ """ for n in self.generator.outdir.ant_glob('**/*.class'): n.sig = Utils.h_file(n.abspath()) # careful with this self.generator.bld.task_sigs[self.uid()] = self.cache_sig @feature('javadoc') @after_method('process_rule') def create_javadoc(self): tsk = self.create_task('javadoc') tsk.classpath = getattr(self, 'classpath', []) self.javadoc_package = Utils.to_list(self.javadoc_package) if not isinstance(self.javadoc_output, Node.Node): self.javadoc_output = self.bld.path.find_or_declare(self.javadoc_output) class javadoc(Task.Task): color = 'BLUE' def __str__(self): return '%s: %s -> %s\n' % (self.__class__.__name__, self.generator.srcdir, self.generator.javadoc_output) def run(self): env = self.env bld = self.generator.bld wd = bld.bldnode.abspath() #add src node + bld node (for generated java code) srcpath = self.generator.path.abspath() + os.sep + self.generator.srcdir srcpath += os.pathsep srcpath += self.generator.path.get_bld().abspath() + os.sep + self.generator.srcdir classpath = env.CLASSPATH classpath += os.pathsep classpath += os.pathsep.join(self.classpath) classpath = "".join(classpath) self.last_cmd = lst = [] lst.extend(Utils.to_list(env['JAVADOC'])) lst.extend(['-d', self.generator.javadoc_output.abspath()]) lst.extend(['-sourcepath', srcpath]) lst.extend(['-classpath', classpath]) lst.extend(['-subpackages']) lst.extend(self.generator.javadoc_package) lst = [x for x in lst if x] self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) def post_run(self): nodes = self.generator.javadoc_output.ant_glob('**') for x in nodes: x.sig = Utils.h_file(x.abspath()) self.generator.bld.task_sigs[self.uid()] = self.cache_sig def configure(self): """ Detect the javac, java and jar programs """ # If JAVA_PATH is set, we prepend it to the path list java_path = self.environ['PATH'].split(os.pathsep) v = self.env if 'JAVA_HOME' in self.environ: java_path = [os.path.join(self.environ['JAVA_HOME'], 'bin')] + java_path self.env['JAVA_HOME'] = [self.environ['JAVA_HOME']] for x in 'javac java jar javadoc'.split(): self.find_program(x, var=x.upper(), path_list=java_path) self.env[x.upper()] = self.cmd_to_list(self.env[x.upper()]) if 'CLASSPATH' in self.environ: v['CLASSPATH'] = self.environ['CLASSPATH'] if not v['JAR']: self.fatal('jar is required for making java packages') if not v['JAVAC']: self.fatal('javac is required for compiling java classes') v['JARCREATE'] = 'cf' # can use cvf v['JAVACFLAGS'] = [] @conf def check_java_class(self, classname, with_classpath=None): """ Check if the specified java class exists :param classname: class to check, like java.util.HashMap :type classname: string :param with_classpath: additional classpath to give :type with_classpath: string """ javatestdir = '.waf-javatest' classpath = javatestdir if self.env['CLASSPATH']: classpath += os.pathsep + self.env['CLASSPATH'] if isinstance(with_classpath, str): classpath += os.pathsep + with_classpath shutil.rmtree(javatestdir, True) os.mkdir(javatestdir) Utils.writef(os.path.join(javatestdir, 'Test.java'), class_check_source) # Compile the source self.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False) # Try to run the app cmd = self.env['JAVA'] + ['-cp', classpath, 'Test', classname] self.to_log("%s\n" % str(cmd)) found = self.exec_command(cmd, shell=False) self.msg('Checking for java class %s' % classname, not found) shutil.rmtree(javatestdir, True) return found @conf def check_jni_headers(conf): """ Check for jni headers and libraries. On success the conf.env variables xxx_JAVA are added for use in C/C++ targets:: def options(opt): opt.load('compiler_c') def configure(conf): conf.load('compiler_c java') conf.check_jni_headers() def build(bld): bld.shlib(source='a.c', target='app', use='JAVA') """ if not conf.env.CC_NAME and not conf.env.CXX_NAME: conf.fatal('load a compiler first (gcc, g++, ..)') if not conf.env.JAVA_HOME: conf.fatal('set JAVA_HOME in the system environment') # jni requires the jvm javaHome = conf.env['JAVA_HOME'][0] dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/include') if dir is None: dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/../Headers') # think different?! if dir is None: conf.fatal('JAVA_HOME does not seem to be set properly') f = dir.ant_glob('**/(jni|jni_md).h') incDirs = [x.parent.abspath() for x in f] dir = conf.root.find_dir(conf.env.JAVA_HOME[0]) f = dir.ant_glob('**/*jvm.(so|dll|dylib)') libDirs = [x.parent.abspath() for x in f] or [javaHome] # On windows, we need both the .dll and .lib to link. On my JDK, they are # in different directories... f = dir.ant_glob('**/*jvm.(lib)') if f: libDirs = [[x, y.parent.abspath()] for x in libDirs for y in f] for d in libDirs: try: conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA') except Exception: pass else: break else: conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) debian/waf-1.7/waflib/Tools/c_tests.py0000664000000000000000000001336312145745420014644 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Various configuration tests. """ from waflib import Task from waflib.Configure import conf from waflib.TaskGen import feature, before_method, after_method import sys LIB_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllexport) #else #define testEXPORT #endif testEXPORT int lib_func(void) { return 9; } ''' MAIN_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllimport) #else #define testEXPORT #endif testEXPORT int lib_func(void); int main(int argc, char **argv) { (void)argc; (void)argv; return !(lib_func() == 9); } ''' @feature('link_lib_test') @before_method('process_source') def link_lib_test_fun(self): """ The configuration test :py:func:`waflib.Tools.ccroot.run_c_code` declares a unique task generator, so we need to create other task generators from here to check if the linker is able to link libraries. """ def write_test_file(task): task.outputs[0].write(task.generator.code) rpath = [] if getattr(self, 'add_rpath', False): rpath = [self.bld.path.get_bld().abspath()] mode = self.mode m = '%s %s' % (mode, mode) ex = self.test_exec and 'test_exec' or '' bld = self.bld bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE) bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE) bld(features='%sshlib' % m, source='test.' + mode, target='test') bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath) @conf def check_library(self, mode=None, test_exec=True): """ Check if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`. :param mode: c or cxx or d :type mode: string """ if not mode: mode = 'c' if self.env.CXX: mode = 'cxx' self.check( compile_filename = [], features = 'link_lib_test', msg = 'Checking for libraries', mode = mode, test_exec = test_exec, ) ######################################################################################## INLINE_CODE = ''' typedef int foo_t; static %s foo_t static_foo () {return 0; } %s foo_t foo () { return 0; } ''' INLINE_VALUES = ['inline', '__inline__', '__inline'] @conf def check_inline(self, **kw): """ Check for the right value for inline macro. Define INLINE_MACRO to 1 if the define is found. If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__) :param define_name: define INLINE_MACRO by default to 1 if the macro is defined :type define_name: string :param features: by default *c* or *cxx* depending on the compiler present :type features: list of string """ self.start_msg('Checking for inline') if not 'define_name' in kw: kw['define_name'] = 'INLINE_MACRO' if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx'] else: kw['features'] = ['c'] for x in INLINE_VALUES: kw['fragment'] = INLINE_CODE % (x, x) try: self.check(**kw) except self.errors.ConfigurationError: continue else: self.end_msg(x) if x != 'inline': self.define('inline', x, quote=False) return x self.fatal('could not use inline functions') ######################################################################################## LARGE_FRAGMENT = '''#include int main(int argc, char **argv) { (void)argc; (void)argv; return !(sizeof(off_t) >= 8); } ''' @conf def check_large_file(self, **kw): """ Check for large file support and define the macro HAVE_LARGEFILE The test is skipped on win32 systems (DEST_BINFMT == pe). :param define_name: define to set, by default *HAVE_LARGEFILE* :type define_name: string :param execute: execute the test (yes by default) :type execute: bool """ if not 'define_name' in kw: kw['define_name'] = 'HAVE_LARGEFILE' if not 'execute' in kw: kw['execute'] = True if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx', 'cxxprogram'] else: kw['features'] = ['c', 'cprogram'] kw['fragment'] = LARGE_FRAGMENT kw['msg'] = 'Checking for large file support' ret = True try: if self.env.DEST_BINFMT != 'pe': ret = self.check(**kw) except self.errors.ConfigurationError: pass else: if ret: return True kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64' kw['defines'] = ['_FILE_OFFSET_BITS=64'] try: ret = self.check(**kw) except self.errors.ConfigurationError: pass else: self.define('_FILE_OFFSET_BITS', 64) return ret self.fatal('There is no support for large files') ######################################################################################## ENDIAN_FRAGMENT = ''' short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; ''' class grep_for_endianness(Task.Task): color = 'PINK' def run(self): txt = self.inputs[0].read(flags='rb').decode('iso8859-1') if txt.find('LiTTleEnDian') > -1: self.generator.tmp.append('little') elif txt.find('BIGenDianSyS') > -1: self.generator.tmp.append('big') else: return -1 @feature('grep_for_endianness') @after_method('process_source') def grep_for_endianness_fun(self): self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) @conf def check_endianness(self): """ Execute a configuration test to determine the endianness """ tmp = [] def check_msg(self): return tmp[0] self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', msg="Checking for endianness", define='ENDIANNESS', tmp=tmp, okmsg=check_msg) return tmp[0] debian/waf-1.7/waflib/Tools/d.py0000664000000000000000000000571112145745420013421 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2007-2010 (ita) from waflib import Utils, Task, Errors from waflib.TaskGen import taskgen_method, feature, extension from waflib.Tools import d_scan, d_config from waflib.Tools.ccroot import link_task, stlink_task class d(Task.Task): "Compile a d file into an object file" color = 'GREEN' run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' scan = d_scan.scan class d_with_header(d): "Compile a d file and generate a header" run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' class d_header(Task.Task): "Compile d headers" color = 'BLUE' run_str = '${D} ${D_HEADER} ${SRC}' class dprogram(link_task): "Link object files into a d program" run_str = '${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' inst_to = '${BINDIR}' class dshlib(dprogram): "Link object files into a d shared library" inst_to = '${LIBDIR}' class dstlib(stlink_task): "Link object files into a d static library" pass # do not remove @extension('.d', '.di', '.D') def d_hook(self, node): """ Compile *D* files. To get .di files as well as .o files, set the following:: def build(bld): bld.program(source='foo.d', target='app', generate_headers=True) """ ext = Utils.destos_to_binfmt(self.env.DEST_OS) == 'pe' and 'obj' or 'o' out = '%s.%d.%s' % (node.name, self.idx, ext) def create_compiled_task(self, name, node): task = self.create_task(name, node, node.parent.find_or_declare(out)) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task if getattr(self, 'generate_headers', None): tsk = create_compiled_task(self, 'd_with_header', node) tsk.outputs.append(node.change_ext(self.env['DHEADER_ext'])) else: tsk = create_compiled_task(self, 'd', node) return tsk @taskgen_method def generate_header(self, filename): """ See feature request #104:: def build(bld): tg = bld.program(source='foo.d', target='app') tg.generate_header('blah.d') # is equivalent to: #tg = bld.program(source='foo.d', target='app', header_lst='blah.d') :param filename: header to create :type filename: string """ try: self.header_lst.append([filename, self.install_path]) except AttributeError: self.header_lst = [[filename, self.install_path]] @feature('d') def process_header(self): """ Process the attribute 'header_lst' to create the d header compilation tasks:: def build(bld): bld.program(source='foo.d', target='app', header_lst='blah.d') """ for i in getattr(self, 'header_lst', []): node = self.path.find_resource(i[0]) if not node: raise Errors.WafError('file %r not found on d obj' % i[0]) self.create_task('d_header', node, node.change_ext('.di')) debian/waf-1.7/waflib/Tools/d_scan.py0000664000000000000000000001200712145745420014421 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Provide a scanner for finding dependencies on d files """ import re from waflib import Utils, Logs def filter_comments(filename): """ :param filename: d file name :type filename: string :rtype: list :return: a list of characters """ txt = Utils.readf(filename) i = 0 buf = [] max = len(txt) begin = 0 while i < max: c = txt[i] if c == '"' or c == "'": # skip a string or character literal buf.append(txt[begin:i]) delim = c i += 1 while i < max: c = txt[i] if c == delim: break elif c == '\\': # skip the character following backslash i += 1 i += 1 i += 1 begin = i elif c == '/': # try to replace a comment with whitespace buf.append(txt[begin:i]) i += 1 if i == max: break c = txt[i] if c == '+': # eat nesting /+ +/ comment i += 1 nesting = 1 c = None while i < max: prev = c c = txt[i] if prev == '/' and c == '+': nesting += 1 c = None elif prev == '+' and c == '/': nesting -= 1 if nesting == 0: break c = None i += 1 elif c == '*': # eat /* */ comment i += 1 c = None while i < max: prev = c c = txt[i] if prev == '*' and c == '/': break i += 1 elif c == '/': # eat // comment i += 1 while i < max and txt[i] != '\n': i += 1 else: # no comment begin = i - 1 continue i += 1 begin = i buf.append(' ') else: i += 1 buf.append(txt[begin:]) return buf class d_parser(object): """ Parser for d files """ def __init__(self, env, incpaths): #self.code = '' #self.module = '' #self.imports = [] self.allnames = [] self.re_module = re.compile("module\s+([^;]+)") self.re_import = re.compile("import\s+([^;]+)") self.re_import_bindings = re.compile("([^:]+):(.*)") self.re_import_alias = re.compile("[^=]+=(.+)") self.env = env self.nodes = [] self.names = [] self.incpaths = incpaths def tryfind(self, filename): """ Search file a file matching an module/import directive :param filename: file to read :type filename: string """ found = 0 for n in self.incpaths: found = n.find_resource(filename.replace('.', '/') + '.d') if found: self.nodes.append(found) self.waiting.append(found) break if not found: if not filename in self.names: self.names.append(filename) def get_strings(self, code): """ :param code: d code to parse :type code: string :return: the modules that the code uses :rtype: a list of match objects """ #self.imports = [] self.module = '' lst = [] # get the module name (if present) mod_name = self.re_module.search(code) if mod_name: self.module = re.sub('\s+', '', mod_name.group(1)) # strip all whitespaces # go through the code, have a look at all import occurrences # first, lets look at anything beginning with "import" and ending with ";" import_iterator = self.re_import.finditer(code) if import_iterator: for import_match in import_iterator: import_match_str = re.sub('\s+', '', import_match.group(1)) # strip all whitespaces # does this end with an import bindings declaration? # (import bindings always terminate the list of imports) bindings_match = self.re_import_bindings.match(import_match_str) if bindings_match: import_match_str = bindings_match.group(1) # if so, extract the part before the ":" (since the module declaration(s) is/are located there) # split the matching string into a bunch of strings, separated by a comma matches = import_match_str.split(',') for match in matches: alias_match = self.re_import_alias.match(match) if alias_match: # is this an alias declaration? (alias = module name) if so, extract the module name match = alias_match.group(1) lst.append(match) return lst def start(self, node): """ The parsing starts here :param node: input file :type node: :py:class:`waflib.Node.Node` """ self.waiting = [node] # while the stack is not empty, add the dependencies while self.waiting: nd = self.waiting.pop(0) self.iter(nd) def iter(self, node): """ Find all the modules that a file depends on, uses :py:meth:`waflib.Tools.d_scan.d_parser.tryfind` to process dependent files :param node: input file :type node: :py:class:`waflib.Node.Node` """ path = node.abspath() # obtain the absolute path code = "".join(filter_comments(path)) # read the file and filter the comments names = self.get_strings(code) # obtain the import strings for x in names: # optimization if x in self.allnames: continue self.allnames.append(x) # for each name, see if it is like a node or not self.tryfind(x) def scan(self): "look for .d/.di used by a d file" env = self.env gruik = d_parser(env, self.generator.includes_nodes) node = self.inputs[0] gruik.start(node) nodes = gruik.nodes names = gruik.names if Logs.verbose: Logs.debug('deps: deps for %s: %r; unresolved %r' % (str(node), nodes, names)) return (nodes, names) debian/waf-1.7/waflib/Tools/glib2.py0000664000000000000000000002777012145745420014206 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for GLib2 tools: * marshal * enums * gsettings """ import os from waflib import Task, Utils, Options, Errors, Logs from waflib.TaskGen import taskgen_method, before_method, after_method, feature ################## marshal files @taskgen_method def add_marshal_file(self, filename, prefix): """ Add a file to the list of marshal files to process. Store them in the attribute *marshal_list*. :param filename: xml file to compile :type filename: string :param prefix: marshal prefix (--prefix=prefix) :type prefix: string """ if not hasattr(self, 'marshal_list'): self.marshal_list = [] self.meths.append('process_marshal') self.marshal_list.append((filename, prefix)) @before_method('process_source') def process_marshal(self): """ Process the marshal files stored in the attribute *marshal_list* to create :py:class:`waflib.Tools.glib2.glib_genmarshal` instances. Add the c file created to the list of source to process. """ for f, prefix in getattr(self, 'marshal_list', []): node = self.path.find_resource(f) if not node: raise Errors.WafError('file not found %r' % f) h_node = node.change_ext('.h') c_node = node.change_ext('.c') task = self.create_task('glib_genmarshal', node, [h_node, c_node]) task.env.GLIB_GENMARSHAL_PREFIX = prefix self.source = self.to_nodes(getattr(self, 'source', [])) self.source.append(c_node) class glib_genmarshal(Task.Task): def run(self): bld = self.inputs[0].__class__.ctx get = self.env.get_flat cmd1 = "%s %s --prefix=%s --header > %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[0].abspath() ) ret = bld.exec_command(cmd1) if ret: return ret #print self.outputs[1].abspath() c = '''#include "%s"\n''' % self.outputs[0].name self.outputs[1].write(c) cmd2 = "%s %s --prefix=%s --body >> %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[1].abspath() ) return bld.exec_command(cmd2) vars = ['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'] color = 'BLUE' ext_out = ['.h'] ########################## glib-mkenums @taskgen_method def add_enums_from_template(self, source='', target='', template='', comments=''): """ Add a file to the list of enum files to process. Store them in the attribute *enums_list*. :param source: enum file to process :type source: string :param target: target file :type target: string :param template: template file :type template: string :param comments: comments :type comments: string """ if not hasattr(self, 'enums_list'): self.enums_list = [] self.meths.append('process_enums') self.enums_list.append({'source': source, 'target': target, 'template': template, 'file-head': '', 'file-prod': '', 'file-tail': '', 'enum-prod': '', 'value-head': '', 'value-prod': '', 'value-tail': '', 'comments': comments}) @taskgen_method def add_enums(self, source='', target='', file_head='', file_prod='', file_tail='', enum_prod='', value_head='', value_prod='', value_tail='', comments=''): """ Add a file to the list of enum files to process. Store them in the attribute *enums_list*. :param source: enum file to process :type source: string :param target: target file :type target: string :param file_head: unused :param file_prod: unused :param file_tail: unused :param enum_prod: unused :param value_head: unused :param value_prod: unused :param value_tail: unused :param comments: comments :type comments: string """ if not hasattr(self, 'enums_list'): self.enums_list = [] self.meths.append('process_enums') self.enums_list.append({'source': source, 'template': '', 'target': target, 'file-head': file_head, 'file-prod': file_prod, 'file-tail': file_tail, 'enum-prod': enum_prod, 'value-head': value_head, 'value-prod': value_prod, 'value-tail': value_tail, 'comments': comments}) @before_method('process_source') def process_enums(self): """ Process the enum files stored in the attribute *enum_list* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. """ for enum in getattr(self, 'enums_list', []): task = self.create_task('glib_mkenums') env = task.env inputs = [] # process the source source_list = self.to_list(enum['source']) if not source_list: raise Errors.WafError('missing source ' + str(enum)) source_list = [self.path.find_resource(k) for k in source_list] inputs += source_list env['GLIB_MKENUMS_SOURCE'] = [k.abspath() for k in source_list] # find the target if not enum['target']: raise Errors.WafError('missing target ' + str(enum)) tgt_node = self.path.find_or_declare(enum['target']) if tgt_node.name.endswith('.c'): self.source.append(tgt_node) env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath() options = [] if enum['template']: # template, if provided template_node = self.path.find_resource(enum['template']) options.append('--template %s' % (template_node.abspath())) inputs.append(template_node) params = {'file-head' : '--fhead', 'file-prod' : '--fprod', 'file-tail' : '--ftail', 'enum-prod' : '--eprod', 'value-head' : '--vhead', 'value-prod' : '--vprod', 'value-tail' : '--vtail', 'comments': '--comments'} for param, option in params.items(): if enum[param]: options.append('%s %r' % (option, enum[param])) env['GLIB_MKENUMS_OPTIONS'] = ' '.join(options) # update the task instance task.set_inputs(inputs) task.set_outputs(tgt_node) class glib_mkenums(Task.Task): """ Process enum files """ run_str = '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' color = 'PINK' ext_out = ['.h'] ######################################### gsettings @taskgen_method def add_settings_schemas(self, filename_list): """ Add settings files to process, add them to *settings_schema_files* :param filename_list: files :type filename_list: list of string """ if not hasattr(self, 'settings_schema_files'): self.settings_schema_files = [] if not isinstance(filename_list, list): filename_list = [filename_list] self.settings_schema_files.extend(filename_list) @taskgen_method def add_settings_enums(self, namespace, filename_list): """ This function may be called only once by task generator to set the enums namespace. :param namespace: namespace :type namespace: string :param filename_list: enum files to process :type filename_list: file list """ if hasattr(self, 'settings_enum_namespace'): raise Errors.WafError("Tried to add gsettings enums to '%s' more than once" % self.name) self.settings_enum_namespace = namespace if type(filename_list) != 'list': filename_list = [filename_list] self.settings_enum_files = filename_list def r_change_ext(self, ext): """ Change the extension from the *last* dot in the filename. The gsettings schemas often have names of the form org.gsettings.test.gschema.xml """ name = self.name k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext return self.parent.find_or_declare([name]) @feature('glib2') def process_settings(self): """ Process the schema files in *settings_schema_files* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. The same files are validated through :py:class:`waflib.Tools.glib2.glib_validate_schema` tasks. """ enums_tgt_node = [] install_files = [] settings_schema_files = getattr(self, 'settings_schema_files', []) if settings_schema_files and not self.env['GLIB_COMPILE_SCHEMAS']: raise Errors.WafError ("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") # 1. process gsettings_enum_files (generate .enums.xml) # if hasattr(self, 'settings_enum_files'): enums_task = self.create_task('glib_mkenums') source_list = self.settings_enum_files source_list = [self.path.find_resource(k) for k in source_list] enums_task.set_inputs(source_list) enums_task.env['GLIB_MKENUMS_SOURCE'] = [k.abspath() for k in source_list] target = self.settings_enum_namespace + '.enums.xml' tgt_node = self.path.find_or_declare(target) enums_task.set_outputs(tgt_node) enums_task.env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath() enums_tgt_node = [tgt_node] install_files.append (tgt_node) options = '--comments "" --fhead "" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " " --vtail " " --ftail "" ' % (self.settings_enum_namespace) enums_task.env['GLIB_MKENUMS_OPTIONS'] = options # 2. process gsettings_schema_files (validate .gschema.xml files) # for schema in settings_schema_files: schema_task = self.create_task ('glib_validate_schema') schema_node = self.path.find_resource(schema) if not schema_node: raise Errors.WafError("Cannot find the schema file '%s'" % schema) install_files.append(schema_node) source_list = enums_tgt_node + [schema_node] schema_task.set_inputs (source_list) schema_task.env['GLIB_COMPILE_SCHEMAS_OPTIONS'] = [("--schema-file=" + k.abspath()) for k in source_list] target_node = r_change_ext (schema_node, '.xml.valid') schema_task.set_outputs (target_node) schema_task.env['GLIB_VALIDATE_SCHEMA_OUTPUT'] = target_node.abspath() # 3. schemas install task def compile_schemas_callback(bld): if not bld.is_install: return Logs.pprint ('YELLOW','Updating GSettings schema cache') command = Utils.subst_vars("${GLIB_COMPILE_SCHEMAS} ${GSETTINGSSCHEMADIR}", bld.env) ret = self.bld.exec_command(command) if self.bld.is_install: if not self.env['GSETTINGSSCHEMADIR']: raise Errors.WafError ('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') if install_files: self.bld.install_files (self.env['GSETTINGSSCHEMADIR'], install_files) if not hasattr(self.bld, '_compile_schemas_registered'): self.bld.add_post_fun (compile_schemas_callback) self.bld._compile_schemas_registered = True class glib_validate_schema(Task.Task): """ Validate schema files """ run_str = 'rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' color = 'PINK' def configure(conf): """ Find the following programs: * *glib-genmarshal* and set *GLIB_GENMARSHAL* * *glib-mkenums* and set *GLIB_MKENUMS* * *glib-compile-schemas* and set *GLIB_COMPILE_SCHEMAS* (not mandatory) And set the variable *GSETTINGSSCHEMADIR* """ conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') conf.find_perl_program('glib-mkenums', var='GLIB_MKENUMS') # when cross-compiling, gsettings.m4 locates the program with the following: # pkg-config --variable glib_compile_schemas gio-2.0 conf.find_program('glib-compile-schemas', var='GLIB_COMPILE_SCHEMAS', mandatory=False) def getstr(varname): return getattr(Options.options, varname, getattr(conf.env,varname, '')) # TODO make this dependent on the gnu_dirs tool? gsettingsschemadir = getstr('GSETTINGSSCHEMADIR') if not gsettingsschemadir: datadir = getstr('DATADIR') if not datadir: prefix = conf.env['PREFIX'] datadir = os.path.join(prefix, 'share') gsettingsschemadir = os.path.join(datadir, 'glib-2.0', 'schemas') conf.env['GSETTINGSSCHEMADIR'] = gsettingsschemadir def options(opt): """ Add the ``--gsettingsschemadir`` command-line option """ opt.add_option('--gsettingsschemadir', help='GSettings schema location [Default: ${datadir}/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR') debian/waf-1.7/waflib/Tools/icc.py0000664000000000000000000000167312145745420013737 0ustar #!/usr/bin/env python # encoding: utf-8 # Stian Selnes, 2008 # Thomas Nagy 2009-2010 (ita) """ Detect the Intel C compiler """ import os, sys from waflib.Tools import ccroot, ar, gcc from waflib.Configure import conf @conf def find_icc(conf): """ Find the program icc and execute it to ensure it really is icc """ if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('icc', var='CC') if not cc: cc = conf.find_program('ICL', var='CC') if not cc: conf.fatal('Intel C Compiler (icc) was not found') cc = conf.cmd_to_list(cc) conf.get_cc_version(cc, icc=True) v['CC'] = cc v['CC_NAME'] = 'icc' def configure(conf): conf.find_icc() conf.find_ar() conf.gcc_common_flags() conf.gcc_modifier_platform() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/Tools/gas.py0000664000000000000000000000064512145745420013751 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) "Detect as/gas/gcc for compiling assembly files" import waflib.Tools.asm # - leave this from waflib.Tools import ar def configure(conf): """ Find the programs gas/as/gcc and set the variable *AS* """ conf.find_program(['gas', 'gcc'], var='AS') conf.env.AS_TGT_F = ['-c', '-o'] conf.env.ASLNK_TGT_F = ['-o'] conf.find_ar() conf.load('asm') debian/waf-1.7/waflib/Tools/ccroot.py0000664000000000000000000005044712145745420014475 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Classes and methods shared by tools providing support for C-like language such as C/C++/D/Assembly/Go (this support module is almost never used alone). """ import os, re from waflib import Task, Utils, Node, Errors from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests from waflib.Configure import conf SYSTEM_LIB_PATHS = ['/usr/lib64', '/usr/lib', '/usr/local/lib64', '/usr/local/lib'] USELIB_VARS = Utils.defaultdict(set) """ Mapping for features to :py:class:`waflib.ConfigSet.ConfigSet` variables. See :py:func:`waflib.Tools.ccroot.propagate_uselib_vars`. """ USELIB_VARS['c'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CCDEPS', 'CFLAGS', 'ARCH']) USELIB_VARS['cxx'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CXXDEPS', 'CXXFLAGS', 'ARCH']) USELIB_VARS['d'] = set(['INCLUDES', 'DFLAGS']) USELIB_VARS['includes'] = set(['INCLUDES', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cprogram'] = USELIB_VARS['cxxprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cshlib'] = USELIB_VARS['cxxshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cstlib'] = USELIB_VARS['cxxstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['dprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['asm'] = set(['ASFLAGS']) # ================================================================================================= @taskgen_method def create_compiled_task(self, name, node): """ Create the compilation task: c, cxx, asm, etc. The output node is created automatically (object file with a typical **.o** extension). The task is appended to the list *compiled_tasks* which is then used by :py:func:`waflib.Tools.ccroot.apply_link` :param name: name of the task class :type name: string :param node: the file to compile :type node: :py:class:`waflib.Node.Node` :return: The task created :rtype: :py:class:`waflib.Task.Task` """ out = '%s.%d.o' % (node.name, self.idx) task = self.create_task(name, node, node.parent.find_or_declare(out)) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task @taskgen_method def to_incnodes(self, inlst): """ Task generator method provided to convert a list of string/nodes into a list of includes folders. The paths are assumed to be relative to the task generator path, except if they begin by **#** in which case they are searched from the top-level directory (``bld.srcnode``). The folders are simply assumed to be existing. The node objects in the list are returned in the output list. The strings are converted into node objects if possible. The node is searched from the source directory, and if a match is found, the equivalent build directory is created and added to the returned list too. When a folder cannot be found, it is ignored. :param inlst: list of folders :type inlst: space-delimited string or a list of string/nodes :rtype: list of :py:class:`waflib.Node.Node` :return: list of include folders as nodes """ lst = [] seen = set([]) for x in self.to_list(inlst): if x in seen or not x: continue seen.add(x) if isinstance(x, Node.Node): lst.append(x) else: if os.path.isabs(x): lst.append(self.bld.root.make_node(x) or x) else: if x[0] == '#': p = self.bld.bldnode.make_node(x[1:]) v = self.bld.srcnode.make_node(x[1:]) else: p = self.path.get_bld().make_node(x) v = self.path.make_node(x) if p.is_child_of(self.bld.bldnode): p.mkdir() lst.append(p) lst.append(v) return lst @feature('c', 'cxx', 'd', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): """ Task generator method that processes the attribute *includes*:: tg = bld(features='includes', includes='.') The folders only need to be relative to the current directory, the equivalent build directory is added automatically (for headers created in the build directory). This enable using a build directory or not (``top == out``). This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, and the list of include paths in ``tg.env.INCLUDES``. """ lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) self.includes_nodes = lst self.env['INCPATHS'] = [x.abspath() for x in lst] class link_task(Task.Task): """ Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib """ color = 'YELLOW' inst_to = None """Default installation path for the link task outputs, or None to disable""" chmod = Utils.O755 """Default installation mode for the link task outputs""" def add_target(self, target): """ Process the *target* attribute to add the platform-specific prefix/suffix such as *.so* or *.exe*. The settings are retrieved from ``env.clsname_PATTERN`` """ if isinstance(target, str): pattern = self.env[self.__class__.__name__ + '_PATTERN'] if not pattern: pattern = '%s' folder, name = os.path.split(target) if self.__class__.__name__.find('shlib') > 0: if self.env.DEST_BINFMT == 'pe' and getattr(self.generator, 'vnum', None): # include the version in the dll file name, # the import lib file name stays unversionned. name = name + '-' + self.generator.vnum.split('.')[0] tmp = folder + os.sep + pattern % name target = self.generator.path.find_or_declare(tmp) self.set_outputs(target) class stlink_task(link_task): """ Base for static link tasks, which use *ar* most of the time. The target is always removed before being written. """ run_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' def rm_tgt(cls): old = cls.run def wrap(self): try: os.remove(self.outputs[0].abspath()) except OSError: pass return old(self) setattr(cls, 'run', wrap) rm_tgt(stlink_task) @feature('c', 'cxx', 'd', 'fc', 'asm') @after_method('process_source') def apply_link(self): """ Collect the tasks stored in ``compiled_tasks`` (created by :py:func:`waflib.Tools.ccroot.create_compiled_task`), and use the outputs for a new instance of :py:class:`waflib.Tools.ccroot.link_task`. The class to use is the first link task matching a name from the attribute *features*, for example:: def build(bld): tg = bld(features='cxx cxxprogram cprogram', source='main.c', target='app') will create the task ``tg.link_task`` as a new instance of :py:class:`waflib.Tools.cxx.cxxprogram` """ for x in self.features: if x == 'cprogram' and 'cxx' in self.features: # limited compat x = 'cxxprogram' elif x == 'cshlib' and 'cxx' in self.features: x = 'cxxshlib' if x in Task.classes: if issubclass(Task.classes[x], link_task): link = x break else: return objs = [t.outputs[0] for t in getattr(self, 'compiled_tasks', [])] self.link_task = self.create_task(link, objs) self.link_task.add_target(self.target) # remember that the install paths are given by the task generators try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.__class__.inst_to if inst_to: # install a copy of the node list we have at this moment (implib not added) self.install_task = self.bld.install_files(inst_to, self.link_task.outputs[:], env=self.env, chmod=self.link_task.chmod) @taskgen_method def use_rec(self, name, **kw): """ Processes the ``use`` keyword recursively. This method is kind of private and only meant to be used from ``process_use`` """ if name in self.tmp_use_not or name in self.tmp_use_seen: return try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: self.uselib.append(name) self.tmp_use_not.add(name) return self.tmp_use_seen.append(name) y.post() # bind temporary attributes on the task generator y.tmp_use_objects = objects = kw.get('objects', True) y.tmp_use_stlib = stlib = kw.get('stlib', True) try: link_task = y.link_task except AttributeError: y.tmp_use_var = '' else: objects = False if not isinstance(link_task, stlink_task): stlib = False y.tmp_use_var = 'LIB' else: y.tmp_use_var = 'STLIB' p = self.tmp_use_prec for x in self.to_list(getattr(y, 'use', [])): try: p[x].append(name) except KeyError: p[x] = [name] self.use_rec(x, objects=objects, stlib=stlib) @feature('c', 'cxx', 'd', 'use', 'fc') @before_method('apply_incpaths', 'propagate_uselib_vars') @after_method('apply_link', 'process_source') def process_use(self): """ Process the ``use`` attribute which contains a list of task generator names:: def build(bld): bld.shlib(source='a.c', target='lib1') bld.program(source='main.c', target='app', use='lib1') See :py:func:`waflib.Tools.ccroot.use_rec`. """ use_not = self.tmp_use_not = set([]) self.tmp_use_seen = [] # we would like an ordered set use_prec = self.tmp_use_prec = {} self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'use', [])) for x in names: self.use_rec(x) for x in use_not: if x in use_prec: del use_prec[x] # topological sort out = [] tmp = [] for x in self.tmp_use_seen: for k in use_prec.values(): if x in k: break else: tmp.append(x) while tmp: e = tmp.pop() out.append(e) try: nlst = use_prec[e] except KeyError: pass else: del use_prec[e] for x in nlst: for y in use_prec: if x in use_prec[y]: break else: tmp.append(x) if use_prec: raise Errors.WafError('Cycle detected in the use processing %r' % use_prec) out.reverse() link_task = getattr(self, 'link_task', None) for x in out: y = self.bld.get_tgen_by_name(x) var = y.tmp_use_var if var and link_task: if var == 'LIB' or y.tmp_use_stlib: self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) self.link_task.dep_nodes.extend(y.link_task.outputs) tmp_path = y.link_task.outputs[0].parent.path_from(self.bld.bldnode) self.env.append_value(var + 'PATH', [tmp_path]) else: if y.tmp_use_objects: self.add_objects_from_tgen(y) if getattr(y, 'export_includes', None): self.includes.extend(y.to_incnodes(y.export_includes)) if getattr(y, 'export_defines', None): self.env.append_value('DEFINES', self.to_list(y.export_defines)) # and finally, add the uselib variables (no recursion needed) for x in names: try: y = self.bld.get_tgen_by_name(x) except Exception: if not self.env['STLIB_' + x] and not x in self.uselib: self.uselib.append(x) else: for k in self.to_list(getattr(y, 'uselib', [])): if not self.env['STLIB_' + k] and not k in self.uselib: self.uselib.append(k) @taskgen_method def accept_node_to_link(self, node): """ PRIVATE INTERNAL USE ONLY """ return not node.name.endswith('.pdb') @taskgen_method def add_objects_from_tgen(self, tg): """ Add the objects from the depending compiled tasks as link task inputs. Some objects are filtered: for instance, .pdb files are added to the compiled tasks but not to the link tasks (to avoid errors) PRIVATE INTERNAL USE ONLY """ try: link_task = self.link_task except AttributeError: pass else: for tsk in getattr(tg, 'compiled_tasks', []): for x in tsk.outputs: if self.accept_node_to_link(x): link_task.inputs.append(x) @taskgen_method def get_uselib_vars(self): """ :return: the *uselib* variables associated to the *features* attribute (see :py:attr:`waflib.Tools.ccroot.USELIB_VARS`) :rtype: list of string """ _vars = set([]) for x in self.features: if x in USELIB_VARS: _vars |= USELIB_VARS[x] return _vars @feature('c', 'cxx', 'd', 'fc', 'javac', 'cs', 'uselib', 'asm') @after_method('process_use') def propagate_uselib_vars(self): """ Process uselib variables for adding flags. For example, the following target:: def build(bld): bld.env.AFLAGS_aaa = ['bar'] from waflib.Tools.ccroot import USELIB_VARS USELIB_VARS['aaa'] = set('AFLAGS') tg = bld(features='aaa', aflags='test') The *aflags* attribute will be processed and this method will set:: tg.env.AFLAGS = ['bar', 'test'] """ _vars = self.get_uselib_vars() env = self.env for x in _vars: y = x.lower() env.append_unique(x, self.to_list(getattr(self, y, []))) for x in self.features: for var in _vars: compvar = '%s_%s' % (var, x) env.append_value(var, env[compvar]) for x in self.to_list(getattr(self, 'uselib', [])): for v in _vars: env.append_value(v, env[v + '_' + x]) # ============ the code above must not know anything about import libs ========== @feature('cshlib', 'cxxshlib', 'fcshlib') @after_method('apply_link') def apply_implib(self): """ Handle dlls and their import libs on Windows-like systems. A ``.dll.a`` file called *import library* is generated. It must be installed as it is required for linking the library. """ if not self.env.DEST_BINFMT == 'pe': return dll = self.link_task.outputs[0] if isinstance(self.target, Node.Node): name = self.target.name else: name = os.path.split(self.target)[1] implib = self.env['implib_PATTERN'] % name implib = dll.parent.find_or_declare(implib) self.env.append_value('LINKFLAGS', self.env['IMPLIB_ST'] % implib.bldpath()) self.link_task.outputs.append(implib) if getattr(self, 'defs', None) and self.env.DEST_BINFMT == 'pe': node = self.path.find_resource(self.defs) if not node: raise Errors.WafError('invalid def file %r' % self.defs) if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): self.env.append_value('LINKFLAGS', '/def:%s' % node.path_from(self.bld.bldnode)) self.link_task.dep_nodes.append(node) else: #gcc for windows takes *.def file a an input without any special flag self.link_task.inputs.append(node) try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.__class__.inst_to if not inst_to: return self.implib_install_task = self.bld.install_as('${LIBDIR}/%s' % implib.name, implib, self.env) # ============ the code above must not know anything about vnum processing on unix platforms ========= re_vnum = re.compile('^([1-9]\\d*|0)[.]([1-9]\\d*|0)[.]([1-9]\\d*|0)$') @feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') @after_method('apply_link', 'propagate_uselib_vars') def apply_vnum(self): """ Enforce version numbering on shared libraries. The valid version numbers must have at most two dots:: def build(bld): bld.shlib(source='a.c', target='foo', vnum='14.15.16') In this example, ``libfoo.so`` is installed as ``libfoo.so.1.2.3``, and the following symbolic links are created: * ``libfoo.so → libfoo.so.1.2.3`` * ``libfoo.so.1 → libfoo.so.1.2.3`` """ if not getattr(self, 'vnum', '') or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): return link = self.link_task if not re_vnum.match(self.vnum): raise Errors.WafError('Invalid version %r for %r' % (self.vnum, self)) nums = self.vnum.split('.') node = link.outputs[0] libname = node.name if libname.endswith('.dylib'): name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) name2 = libname.replace('.dylib', '.%s.dylib' % nums[0]) else: name3 = libname + '.' + self.vnum name2 = libname + '.' + nums[0] # add the so name for the ld linker - to disable, just unset env.SONAME_ST if self.env.SONAME_ST: v = self.env.SONAME_ST % name2 self.env.append_value('LINKFLAGS', v.split()) # the following task is just to enable execution from the build dir :-/ self.create_task('vnum', node, [node.parent.find_or_declare(name2), node.parent.find_or_declare(name3)]) if getattr(self, 'install_task', None): self.install_task.hasrun = Task.SKIP_ME bld = self.bld path = self.install_task.dest t1 = bld.install_as(path + os.sep + name3, node, env=self.env, chmod=self.link_task.chmod) t2 = bld.symlink_as(path + os.sep + name2, name3) t3 = bld.symlink_as(path + os.sep + libname, name3) self.vnum_install_task = (t1, t2, t3) if '-dynamiclib' in self.env['LINKFLAGS']: # this requires after(propagate_uselib_vars) try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.__class__.inst_to if inst_to: p = Utils.subst_vars(inst_to, self.env) path = os.path.join(p, self.link_task.outputs[0].name) self.env.append_value('LINKFLAGS', ['-install_name', path]) class vnum(Task.Task): """ Create the symbolic links for a versioned shared library. Instances are created by :py:func:`waflib.Tools.ccroot.apply_vnum` """ color = 'CYAN' quient = True ext_in = ['.bin'] def run(self): for x in self.outputs: path = x.abspath() try: os.remove(path) except OSError: pass try: os.symlink(self.inputs[0].name, path) except OSError: return 1 class fake_shlib(link_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME class fake_stlib(stlink_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME @conf def read_shlib(self, name, paths=[]): """ Read a system shared library, enabling its use as a local library. Will trigger a rebuild if the file changes:: def build(bld): bld.read_shlib('m') bld.program(source='main.c', use='m') """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='shlib') @conf def read_stlib(self, name, paths=[]): """ Read a system static library, enabling a use as a local library. Will trigger a rebuild if the file changes. """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='stlib') lib_patterns = { 'shlib' : ['lib%s.so', '%s.so', 'lib%s.dylib', 'lib%s.dll', '%s.dll'], 'stlib' : ['lib%s.a', '%s.a', 'lib%s.dll', '%s.dll', 'lib%s.lib', '%s.lib'], } @feature('fake_lib') def process_lib(self): """ Find the location of a foreign library. Used by :py:class:`waflib.Tools.ccroot.read_shlib` and :py:class:`waflib.Tools.ccroot.read_stlib`. """ node = None names = [x % self.name for x in lib_patterns[self.lib_type]] for x in self.lib_paths + [self.path] + SYSTEM_LIB_PATHS: if not isinstance(x, Node.Node): x = self.bld.root.find_node(x) or self.path.find_node(x) if not x: continue for y in names: node = x.find_node(y) if node: node.sig = Utils.h_file(node.abspath()) break else: continue break else: raise Errors.WafError('could not find library %r' % self.name) self.link_task = self.create_task('fake_%s' % self.lib_type, [], [node]) self.target = self.name class fake_o(Task.Task): def runnable_status(self): return Task.SKIP_ME @extension('.o', '.obj') def add_those_o_files(self, node): tsk = self.create_task('fake_o', [], node) try: self.compiled_tasks.append(tsk) except AttributeError: self.compiled_tasks = [tsk] @feature('fake_obj') @before_method('process_source') def process_objs(self): """ Puts object files in the task generator outputs """ for node in self.to_nodes(self.source): self.add_those_o_files(node) self.source = [] @conf def read_object(self, obj): """ Read an object file, enabling injection in libs/programs. Will trigger a rebuild if the file changes. :param obj: object file path, as string or Node """ if not isinstance(obj, self.path.__class__): obj = self.path.find_resource(obj) return self(features='fake_obj', source=obj, name=obj.name) debian/waf-1.7/waflib/Tools/intltool.py0000664000000000000000000001240512145745420015040 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for translation tools such as msgfmt and intltool Usage:: def configure(conf): conf.load('gnu_dirs intltool') def build(bld): # process the .po files into .gmo files, and install them in LOCALEDIR bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") # process an input file, substituting the translations from the po dir bld( features = "intltool_in", podir = "../po", flags = ["-d", "-q", "-u", "-c"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. """ import os, re from waflib import Configure, TaskGen, Task, Utils, Runner, Options, Build, Logs import waflib.Tools.ccroot from waflib.TaskGen import feature, before_method from waflib.Logs import error @before_method('process_source') @feature('intltool_in') def apply_intltool_in_f(self): """ Create tasks to translate files by intltool-merge:: def build(bld): bld( features = "intltool_in", podir = "../po", flags = ["-d", "-q", "-u", "-c"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) :param podir: location of the .po files :type podir: string :param source: source files to process :type source: list of string :param flags: compilation flags ("-quc" by default) :type flags: list of string :param install_path: installation path :type install_path: string """ try: self.meths.remove('process_source') except ValueError: pass if not self.env.LOCALEDIR: self.env.LOCALEDIR = self.env.PREFIX + '/share/locale' for i in self.to_list(self.source): node = self.path.find_resource(i) podir = getattr(self, 'podir', 'po') podirnode = self.path.find_dir(podir) if not podirnode: error("could not find the podir %r" % podir) continue cache = getattr(self, 'intlcache', '.intlcache') self.env['INTLCACHE'] = os.path.join(self.path.bldpath(), podir, cache) self.env['INTLPODIR'] = podirnode.bldpath() self.env['INTLFLAGS'] = getattr(self, 'flags', ['-q', '-u', '-c']) task = self.create_task('intltool', node, node.change_ext('')) inst = getattr(self, 'install_path', '${LOCALEDIR}') if inst: self.bld.install_files(inst, task.outputs) @feature('intltool_po') def apply_intltool_po(self): """ Create tasks to process po files:: def build(bld): bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") The relevant task generator arguments are: :param podir: directory of the .po files :type podir: string :param appname: name of the application :type appname: string :param install_path: installation directory :type install_path: string The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. """ try: self.meths.remove('process_source') except ValueError: pass if not self.env.LOCALEDIR: self.env.LOCALEDIR = self.env.PREFIX + '/share/locale' appname = getattr(self, 'appname', 'set_your_app_name') podir = getattr(self, 'podir', '') inst = getattr(self, 'install_path', '${LOCALEDIR}') linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) if linguas: # scan LINGUAS file for locales to process file = open(linguas.abspath()) langs = [] for line in file.readlines(): # ignore lines containing comments if not line.startswith('#'): langs += line.split() file.close() re_linguas = re.compile('[-a-zA-Z_@.]+') for lang in langs: # Make sure that we only process lines which contain locales if re_linguas.match(lang): node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) task = self.create_task('po', node, node.change_ext('.mo')) if inst: filename = task.outputs[0].name (langname, ext) = os.path.splitext(filename) inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' self.bld.install_as(inst_file, task.outputs[0], chmod=getattr(self, 'chmod', Utils.O644), env=task.env) else: Logs.pprint('RED', "Error no LINGUAS file found in po directory") class po(Task.Task): """ Compile .po files into .gmo files """ run_str = '${MSGFMT} -o ${TGT} ${SRC}' color = 'BLUE' class intltool(Task.Task): """ Let intltool-merge translate an input file """ run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' color = 'BLUE' def configure(conf): """ Detect the program *msgfmt* and set *conf.env.MSGFMT*. Detect the program *intltool-merge* and set *conf.env.INTLTOOL*. It is possible to set INTLTOOL in the environment, but it must not have spaces in it:: $ INTLTOOL="/path/to/the program/intltool" waf configure If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*. """ conf.find_program('msgfmt', var='MSGFMT') conf.find_perl_program('intltool-merge', var='INTLTOOL') prefix = conf.env.PREFIX datadir = conf.env.DATADIR if not datadir: datadir = os.path.join(prefix,'share') conf.define('LOCALEDIR', os.path.join(datadir, 'locale').replace('\\', '\\\\')) conf.define('DATADIR', datadir.replace('\\', '\\\\')) if conf.env.CC or conf.env.CXX: conf.check(header_name='locale.h') debian/waf-1.7/waflib/Tools/gfortran.py0000664000000000000000000000442612145745420015022 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan, ar from waflib.Configure import conf @conf def find_gfortran(conf): """Find the gfortran program (will look in the environment variable 'FC')""" fc = conf.find_program(['gfortran','g77'], var='FC') # (fallback to g77 for systems, where no gfortran is available) fc = conf.cmd_to_list(fc) conf.get_gfortran_version(fc) conf.env.FC_NAME = 'GFORTRAN' @conf def gfortran_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC'] v['FORTRANMODFLAG'] = ['-J', ''] # template for module path v['FCFLAGS_DEBUG'] = ['-Werror'] # why not @conf def gfortran_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def gfortran_modifier_cygwin(conf): fc_config.fortran_modifier_cygwin(conf) @conf def gfortran_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def gfortran_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() gfortran_modifier_func = getattr(conf, 'gfortran_modifier_' + dest_os, None) if gfortran_modifier_func: gfortran_modifier_func() @conf def get_gfortran_version(conf, fc): """Get the compiler version""" # ensure this is actually gfortran, not an imposter. version_re = re.compile(r"GNU\s*Fortran", re.I).search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the compiler type') # --- now get more detailed info -- see c_config.get_cc_version cmd = fc + ['-dM', '-E', '-'] out, err = fc_config.getoutput(conf, cmd, stdin=True) if out.find('__GNUC__') < 0: conf.fatal('Could not determine the compiler type') k = {} out = out.split('\n') import shlex for line in out: lst = shlex.split(line) if len(lst)>2: key = lst[1] val = lst[2] k[key] = val def isD(var): return var in k def isT(var): return var in k and k[var] != '0' conf.env['FC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) def configure(conf): conf.find_gfortran() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.gfortran_flags() conf.gfortran_modifier_platform() debian/waf-1.7/waflib/Tools/d_config.py0000664000000000000000000000263312145745420014746 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) from waflib import Utils from waflib.Configure import conf @conf def d_platform_flags(self): """ Set the extensions dll/so for d programs and libraries """ v = self.env if not v.DEST_OS: v.DEST_OS = Utils.unversioned_sys_platform() binfmt = Utils.destos_to_binfmt(self.env.DEST_OS) if binfmt == 'pe': v['dprogram_PATTERN'] = '%s.exe' v['dshlib_PATTERN'] = 'lib%s.dll' v['dstlib_PATTERN'] = 'lib%s.a' elif binfmt == 'mac-o': v['dprogram_PATTERN'] = '%s' v['dshlib_PATTERN'] = 'lib%s.dylib' v['dstlib_PATTERN'] = 'lib%s.a' else: v['dprogram_PATTERN'] = '%s' v['dshlib_PATTERN'] = 'lib%s.so' v['dstlib_PATTERN'] = 'lib%s.a' DLIB = ''' version(D_Version2) { import std.stdio; int main() { writefln("phobos2"); return 0; } } else { version(Tango) { import tango.stdc.stdio; int main() { printf("tango"); return 0; } } else { import std.stdio; int main() { writefln("phobos1"); return 0; } } } ''' """Detection string for the D standard library""" @conf def check_dlibrary(self, execute=True): """ Detect the kind of standard library that comes with the compiler, will set conf.env.DLIBRARY to tango, phobos1 or phobos2. """ ret = self.check_cc(features='d dprogram', fragment=DLIB, compile_filename='test.d', execute=execute, define_ret=True) if execute: self.env.DLIBRARY = ret.strip() debian/waf-1.7/waflib/Tools/kde4.py0000664000000000000000000000525412145745420014027 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for the KDE4 libraries and msgfmt """ import os, sys, re from waflib import Options, TaskGen, Task, Utils from waflib.TaskGen import feature, after_method @feature('msgfmt') def apply_msgfmt(self): """ Process all languages to create .mo files and to install them:: def build(bld): bld(features='msgfmt', langs='es de fr', appname='myapp', install_path='${KDE4_LOCALE_INSTALL_DIR}') """ for lang in self.to_list(self.langs): node = self.path.find_resource(lang+'.po') task = self.create_task('msgfmt', node, node.change_ext('.mo')) langname = lang.split('/') langname = langname[-1] inst = getattr(self, 'install_path', '${KDE4_LOCALE_INSTALL_DIR}') self.bld.install_as( inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + getattr(self, 'appname', 'set_your_appname') + '.mo', task.outputs[0], chmod = getattr(self, 'chmod', Utils.O644)) class msgfmt(Task.Task): """ Transform .po files into .mo files """ color = 'BLUE' run_str = '${MSGFMT} ${SRC} -o ${TGT}' def configure(self): """ Detect kde4-config and set various variables for the *use* system:: def options(opt): opt.load('compiler_cxx kde4') def configure(conf): conf.load('compiler_cxx kde4') def build(bld): bld.program(source='main.c', target='app', use='KDECORE KIO KHTML') """ kdeconfig = self.find_program('kde4-config') prefix = self.cmd_and_log('%s --prefix' % kdeconfig).strip() fname = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(fname) except OSError: fname = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(fname) except OSError: self.fatal('could not open %s' % fname) try: txt = Utils.readf(fname) except (OSError, IOError): self.fatal('could not read %s' % fname) txt = txt.replace('\\\n', '\n') fu = re.compile('#(.*)\n') txt = fu.sub('', txt) setregexp = re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') found = setregexp.findall(txt) for (_, key, val) in found: #print key, val self.env[key] = val # well well, i could just write an interpreter for cmake files self.env['LIB_KDECORE']= ['kdecore'] self.env['LIB_KDEUI'] = ['kdeui'] self.env['LIB_KIO'] = ['kio'] self.env['LIB_KHTML'] = ['khtml'] self.env['LIB_KPARTS'] = ['kparts'] self.env['LIBPATH_KDECORE'] = [os.path.join(self.env.KDE4_LIB_INSTALL_DIR, 'kde4', 'devel'), self.env.KDE4_LIB_INSTALL_DIR] self.env['INCLUDES_KDECORE'] = [self.env['KDE4_INCLUDE_INSTALL_DIR']] self.env.append_value('INCLUDES_KDECORE', [self.env['KDE4_INCLUDE_INSTALL_DIR']+ os.sep + 'KDE']) self.find_program('msgfmt', var='MSGFMT') debian/waf-1.7/waflib/Tools/c_config.py0000775000000000000000000010603212145745420014746 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ C/C++/D configuration helpers """ import os, re, shlex, sys from waflib import Build, Utils, Task, Options, Logs, Errors, ConfigSet, Runner from waflib.TaskGen import after_method, feature from waflib.Configure import conf WAF_CONFIG_H = 'config.h' """default name for the config.h file""" DEFKEYS = 'define_key' INCKEYS = 'include_key' cfg_ver = { 'atleast-version': '>=', 'exact-version': '==', 'max-version': '<=', } SNIP_FUNCTION = ''' int main(int argc, char **argv) { void *p; (void)argc; (void)argv; p=(void*)(%s); return 0; } ''' """Code template for checking for functions""" SNIP_TYPE = ''' int main(int argc, char **argv) { (void)argc; (void)argv; if ((%(type_name)s *) 0) return 0; if (sizeof (%(type_name)s)) return 0; return 1; } ''' """Code template for checking for types""" SNIP_EMPTY_PROGRAM = ''' int main(int argc, char **argv) { (void)argc; (void)argv; return 0; } ''' SNIP_FIELD = ''' int main(int argc, char **argv) { char *off; (void)argc; (void)argv; off = (char*) &((%(type_name)s*)0)->%(field_name)s; return (size_t) off < sizeof(%(type_name)s); } ''' MACRO_TO_DESTOS = { '__linux__' : 'linux', '__GNU__' : 'gnu', # hurd '__FreeBSD__' : 'freebsd', '__NetBSD__' : 'netbsd', '__OpenBSD__' : 'openbsd', '__sun' : 'sunos', '__hpux' : 'hpux', '__sgi' : 'irix', '_AIX' : 'aix', '__CYGWIN__' : 'cygwin', '__MSYS__' : 'msys', '_UWIN' : 'uwin', '_WIN64' : 'win32', '_WIN32' : 'win32', # Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file. '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin', '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone '__QNX__' : 'qnx', '__native_client__' : 'nacl' # google native client platform } MACRO_TO_DEST_CPU = { '__x86_64__' : 'x86_64', '__amd64__' : 'x86_64', '__i386__' : 'x86', '__ia64__' : 'ia', '__mips__' : 'mips', '__sparc__' : 'sparc', '__alpha__' : 'alpha', '__aarch64__' : 'aarch64', '__thumb__' : 'thumb', '__arm__' : 'arm', '__hppa__' : 'hppa', '__powerpc__' : 'powerpc', '__ppc__' : 'powerpc', '__convex__' : 'convex', '__m68k__' : 'm68k', '__s390x__' : 's390x', '__s390__' : 's390', '__sh__' : 'sh', } @conf def parse_flags(self, line, uselib_store, env=None, force_static=False): """ Parse the flags from the input lines, and add them to the relevant use variables:: def configure(conf): conf.parse_flags('-O3', 'FOO') # conf.env.CXXFLAGS_FOO = ['-O3'] # conf.env.CFLAGS_FOO = ['-O3'] :param line: flags :type line: string :param uselib_store: where to add the flags :type uselib_store: string :param env: config set or conf.env by default :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ assert(isinstance(line, str)) env = env or self.env # append_unique is not always possible # for example, apple flags may require both -arch i386 and -arch ppc app = env.append_value appu = env.append_unique #lst = shlex.split(line) # issue #811 lex = shlex.shlex(line, posix=False) lex.whitespace_split = True lex.commenters = '' lst = list(lex) uselib = uselib_store while lst: x = lst.pop(0) st = x[:2] ot = x[2:] if st == '-I' or st == '/I': if not ot: ot = lst.pop(0) appu('INCLUDES_' + uselib, [ot]) elif st == '-include': tmp = [x, lst.pop(0)] app('CFLAGS', tmp) app('CXXFLAGS', tmp) elif st == '-D' or (env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but.. if not ot: ot = lst.pop(0) app('DEFINES_' + uselib, [ot]) elif st == '-l': if not ot: ot = lst.pop(0) prefix = force_static and 'STLIB_' or 'LIB_' appu(prefix + uselib, [ot]) elif st == '-L': if not ot: ot = lst.pop(0) appu('LIBPATH_' + uselib, [ot]) elif x.startswith('/LIBPATH:'): appu('LIBPATH_' + uselib, [x.replace('/LIBPATH:', '')]) elif x == '-pthread' or x.startswith('+') or x.startswith('-std'): app('CFLAGS_' + uselib, [x]) app('CXXFLAGS_' + uselib, [x]) app('LINKFLAGS_' + uselib, [x]) elif x == '-framework': appu('FRAMEWORK_' + uselib, [lst.pop(0)]) elif x.startswith('-F'): appu('FRAMEWORKPATH_' + uselib, [x[2:]]) elif x.startswith('-Wl'): app('LINKFLAGS_' + uselib, [x]) elif x.startswith('-m') or x.startswith('-f') or x.startswith('-dynamic'): app('CFLAGS_' + uselib, [x]) app('CXXFLAGS_' + uselib, [x]) elif x.startswith('-bundle'): app('LINKFLAGS_' + uselib, [x]) elif x.startswith('-undefined'): arg = lst.pop(0) app('LINKFLAGS_' + uselib, [x, arg]) elif x.startswith('-arch') or x.startswith('-isysroot'): tmp = [x, lst.pop(0)] app('CFLAGS_' + uselib, tmp) app('CXXFLAGS_' + uselib, tmp) app('LINKFLAGS_' + uselib, tmp) elif x.endswith('.a') or x.endswith('.so') or x.endswith('.dylib') or x.endswith('.lib'): appu('LINKFLAGS_' + uselib, [x]) # not cool, #762 @conf def ret_msg(self, f, kw): if isinstance(f, str): return f return f(kw) @conf def validate_cfg(self, kw): """ Search for the program *pkg-config* if missing, and validate the parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`. :param path: the **-config program to use** (default is *pkg-config*) :type path: list of string :param msg: message to display to describe the test executed :type msg: string :param okmsg: message to display when the test is successful :type okmsg: string :param errmsg: message to display in case of error :type errmsg: string """ if not 'path' in kw: if not self.env.PKGCONFIG: self.find_program('pkg-config', var='PKGCONFIG') kw['path'] = self.env.PKGCONFIG # pkg-config version if 'atleast_pkgconfig_version' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] return if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'errmsg' in kw: kw['errmsg'] = 'not found' if 'modversion' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %r version' % kw['modversion'] return # checking for the version of a module, for the moment, one thing at a time for x in cfg_ver.keys(): y = x.replace('-', '_') if y in kw: if not 'package' in kw: raise ValueError('%s requires a package' % x) if not 'msg' in kw: kw['msg'] = 'Checking for %r %s %s' % (kw['package'], cfg_ver[x], kw[y]) return if not 'msg' in kw: kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path']) @conf def exec_cfg(self, kw): """ Execute the program *pkg-config*: * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return * if modversion is given, then return the module version * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) :type atleast_pkgconfig_version: string :param package: package name, for example *gtk+-2.0* :type package: string :param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables. :type uselib_store: string :param modversion: if provided, return the version of the given module and define *name*\_VERSION :type modversion: string :param args: arguments to give to *package* when retrieving flags :type args: list of string :param variables: return the values of particular variables :type variables: list of string :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) :type define_variable: dict(string: string) """ def define_it(): self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) # pkg-config version if 'atleast_pkgconfig_version' in kw: cmd = [kw['path'], '--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] self.cmd_and_log(cmd) if not 'okmsg' in kw: kw['okmsg'] = 'yes' return # checking for the version of a module for x in cfg_ver: y = x.replace('-', '_') if y in kw: self.cmd_and_log([kw['path'], '--%s=%s' % (x, kw[y]), kw['package']]) if not 'okmsg' in kw: kw['okmsg'] = 'yes' define_it() break # retrieving the version of a module if 'modversion' in kw: version = self.cmd_and_log([kw['path'], '--modversion', kw['modversion']]).strip() self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version) return version lst = [kw['path']] defi = kw.get('define_variable', None) if not defi: defi = self.env.PKG_CONFIG_DEFINES or {} for key, val in defi.items(): lst.append('--define-variable=%s=%s' % (key, val)) # retrieving variables of a module if 'variables' in kw: env = kw.get('env', self.env) uselib = kw.get('uselib_store', kw['package'].upper()) vars = Utils.to_list(kw['variables']) for v in vars: val = self.cmd_and_log(lst + ['--variable=' + v]).strip() var = '%s_%s' % (uselib, v) env[var] = val if not 'okmsg' in kw: kw['okmsg'] = 'yes' return static = False if 'args' in kw: args = Utils.to_list(kw['args']) if '--static' in args or '--static-libs' in args: static = True lst += args # tools like pkgconf expect the package argument after the -- ones -_- lst.extend(Utils.to_list(kw['package'])) # so we assume the command-line will output flags to be parsed afterwards ret = self.cmd_and_log(lst) if not 'okmsg' in kw: kw['okmsg'] = 'yes' define_it() self.parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env), force_static=static) return ret @conf def check_cfg(self, *k, **kw): """ Check for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). Encapsulate the calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` A few examples:: def configure(conf): conf.load('compiler_c') conf.check_cfg(package='glib-2.0', args='--libs --cflags') conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0', args='--cflags --libs') conf.check_cfg(package='pango') conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) conf.check_cfg(package='pango', args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'], msg="Checking for 'pango 0.1.0'") conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL') conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI', mandatory=False) """ if k: lst = k[0].split() kw['package'] = lst[0] kw['args'] = ' '.join(lst[1:]) self.validate_cfg(kw) if 'msg' in kw: self.start_msg(kw['msg']) ret = None try: ret = self.exec_cfg(kw) except self.errors.WafError: if 'errmsg' in kw: self.end_msg(kw['errmsg'], 'YELLOW') if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret if 'okmsg' in kw: self.end_msg(self.ret_msg(kw['okmsg'], kw)) return ret @conf def validate_c(self, kw): """ pre-check the parameters that will be given to run_c_code :param compiler: c or cxx (tries to guess what is best) :type compiler: string :param type: cprogram, cshlib, cstlib - not required if *features are given directly* :type type: binary to create :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib`` :type feature: list of string :param fragment: provide a piece of code for the test (default is to let the system create one) :type fragment: string :param uselib_store: define variables after the test is executed (IMPORTANT!) :type uselib_store: string :param use: parameters to use for building (just like the normal *use* keyword) :type use: list of string :param define_name: define to set when the check is over :type define_name: string :param execute: execute the resulting binary :type execute: bool :param define_ret: if execute is set to True, use the execution output in both the define and the return value :type define_ret: bool :param header_name: check for a particular header :type header_name: string :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers :type auto_add_header_name: bool """ if not 'env' in kw: kw['env'] = self.env.derive() env = kw['env'] if not 'compiler' in kw and not 'features' in kw: kw['compiler'] = 'c' if env['CXX_NAME'] and Task.classes.get('cxx', None): kw['compiler'] = 'cxx' if not self.env['CXX']: self.fatal('a c++ compiler is required') else: if not self.env['CC']: self.fatal('a c compiler is required') if not 'compile_mode' in kw: kw['compile_mode'] = 'c' if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx': kw['compile_mode'] = 'cxx' if not 'type' in kw: kw['type'] = 'cprogram' if not 'features' in kw: kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram c" else: kw['features'] = Utils.to_list(kw['features']) if not 'compile_filename' in kw: kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') def to_header(dct): if 'header_name' in dct: dct = Utils.to_list(dct['header_name']) return ''.join(['#include <%s>\n' % x for x in dct]) return '' #OSX if 'framework_name' in kw: fwkname = kw['framework_name'] if not 'uselib_store' in kw: kw['uselib_store'] = fwkname.upper() if not kw.get('no_header', False): if not 'header_name' in kw: kw['header_name'] = [] fwk = '%s/%s.h' % (fwkname, fwkname) if kw.get('remove_dot_h', None): fwk = fwk[:-2] kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk] kw['msg'] = 'Checking for framework %s' % fwkname kw['framework'] = fwkname #kw['frameworkpath'] = set it yourself if 'function_name' in kw: fu = kw['function_name'] if not 'msg' in kw: kw['msg'] = 'Checking for function %s' % fu kw['code'] = to_header(kw) + SNIP_FUNCTION % fu if not 'uselib_store' in kw: kw['uselib_store'] = fu.upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(fu) elif 'type_name' in kw: tu = kw['type_name'] if not 'header_name' in kw: kw['header_name'] = 'stdint.h' if 'field_name' in kw: field = kw['field_name'] kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field} if not 'msg' in kw: kw['msg'] = 'Checking for field %s in %s' % (field, tu) if not 'define_name' in kw: kw['define_name'] = self.have_define((tu + '_' + field).upper()) else: kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu} if not 'msg' in kw: kw['msg'] = 'Checking for type %s' % tu if not 'define_name' in kw: kw['define_name'] = self.have_define(tu.upper()) elif 'header_name' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for header %s' % kw['header_name'] l = Utils.to_list(kw['header_name']) assert len(l)>0, 'list of headers in header_name is empty' kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM if not 'uselib_store' in kw: kw['uselib_store'] = l[0].upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(l[0]) if 'lib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for library %s' % kw['lib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['lib'].upper() if 'stlib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for static library %s' % kw['stlib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['stlib'].upper() if 'fragment' in kw: # an additional code fragment may be provided to replace the predefined code # in custom headers kw['code'] = kw['fragment'] if not 'msg' in kw: kw['msg'] = 'Checking for code snippet' if not 'errmsg' in kw: kw['errmsg'] = 'no' for (flagsname,flagstype) in [('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')]: if flagsname in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) if not 'errmsg' in kw: kw['errmsg'] = 'no' if not 'execute' in kw: kw['execute'] = False if kw['execute']: kw['features'].append('test_exec') if not 'errmsg' in kw: kw['errmsg'] = 'not found' if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'code' in kw: kw['code'] = SNIP_EMPTY_PROGRAM # if there are headers to append automatically to the next tests if self.env[INCKEYS]: kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] if not kw.get('success'): kw['success'] = None if 'define_name' in kw: self.undefine(kw['define_name']) assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c' @conf def post_check(self, *k, **kw): "Set the variables after a test executed in :py:func:`waflib.Tools.c_config.check` was run successfully" is_success = 0 if kw['execute']: if kw['success'] is not None: if kw.get('define_ret', False): is_success = kw['success'] else: is_success = (kw['success'] == 0) else: is_success = (kw['success'] == 0) if 'define_name' in kw: # TODO simplify? if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str): self.define(kw['define_name'], is_success, quote=kw.get('quote', 1)) else: self.define_cond(kw['define_name'], is_success) else: self.define_cond(kw['define_name'], is_success) if 'header_name' in kw: if kw.get('auto_add_header_name', False): self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) if is_success and 'uselib_store' in kw: from waflib.Tools import ccroot # TODO see get_uselib_vars from ccroot.py _vars = set([]) for x in kw['features']: if x in ccroot.USELIB_VARS: _vars |= ccroot.USELIB_VARS[x] for k in _vars: lk = k.lower() if k == 'INCLUDES': lk = 'includes' if k == 'DEFINES': lk = 'defines' if lk in kw: val = kw[lk] # remove trailing slash if isinstance(val, str): val = val.rstrip(os.path.sep) self.env.append_unique(k + '_' + kw['uselib_store'], val) return is_success @conf def check(self, *k, **kw): """ Perform a configuration test by calling :py:func:`waflib.Tools.c_config.run_c_code`. For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`. To force a specific compiler, prefer the methods :py:func:`waflib.Tools.c_config.check_cxx` or :py:func:`waflib.Tools.c_config.check_cc` """ self.validate_c(kw) self.start_msg(kw['msg']) ret = None try: ret = self.run_c_code(*k, **kw) except self.errors.ConfigurationError: self.end_msg(kw['errmsg'], 'YELLOW') if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret ret = self.post_check(*k, **kw) if not ret: self.end_msg(kw['errmsg'], 'YELLOW') self.fatal('The configuration failed %r' % ret) else: self.end_msg(self.ret_msg(kw['okmsg'], kw)) return ret class test_exec(Task.Task): """ A task for executing a programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`. """ color = 'PINK' def run(self): if getattr(self.generator, 'rpath', None): if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) else: self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()]) else: env = self.env.env or {} env.update(dict(os.environ)) for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env) else: self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env) @feature('test_exec') @after_method('apply_link') def test_exec_fun(self): """ The feature **test_exec** is used to create a task that will to execute the binary created (link task output) during the build. The exit status will be set on the build context, so only one program may have the feature *test_exec*. This is used by configuration tests:: def configure(conf): conf.check(execute=True) """ self.create_task('test_exec', self.link_task.outputs[0]) CACHE_RESULTS = 1 COMPILE_ERRORS = 2 @conf def run_c_code(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes, and you should not rely on it too much (read the note on the cache below). The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except OSError: pass try: os.stat(dir) except OSError: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) except OSError: pass else: ret = proj['cache_run_c_code'] if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret @conf def check_cxx(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *c++* programming language """ kw['compiler'] = 'cxx' return self.check(*k, **kw) @conf def check_cc(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *c* programming language """ kw['compiler'] = 'c' return self.check(*k, **kw) @conf def define(self, key, val, quote=True): """ Store a single define and its state into conf.env.DEFINES. If the value is True, False or None it is cast to 1 or 0. :param key: define name :type key: string :param val: value :type val: int or string :param quote: enclose strings in quotes (yes by default) :type quote: bool """ assert key and isinstance(key, str) if val is True: val = 1 elif val in (False, None): val = 0 if isinstance(val, int) or isinstance(val, float): s = '%s=%s' else: s = quote and '%s="%s"' or '%s=%s' app = s % (key, str(val)) ban = key + '=' lst = self.env['DEFINES'] for x in lst: if x.startswith(ban): lst[lst.index(x)] = app break else: self.env.append_value('DEFINES', app) self.env.append_unique(DEFKEYS, key) @conf def undefine(self, key): """ Remove a define from conf.env.DEFINES :param key: define name :type key: string """ assert key and isinstance(key, str) ban = key + '=' lst = [x for x in self.env['DEFINES'] if not x.startswith(ban)] self.env['DEFINES'] = lst self.env.append_unique(DEFKEYS, key) @conf def define_cond(self, key, val): """ Conditionally define a name:: def configure(conf): conf.define_cond('A', True) # equivalent to: # if val: conf.define('A', 1) # else: conf.undefine('A') :param key: define name :type key: string :param val: value :type val: int or string """ assert key and isinstance(key, str) if val: self.define(key, 1) else: self.undefine(key) @conf def is_defined(self, key): """ :param key: define name :type key: string :return: True if the define is set :rtype: bool """ assert key and isinstance(key, str) ban = key + '=' for x in self.env['DEFINES']: if x.startswith(ban): return True return False @conf def get_define(self, key): """ :param key: define name :type key: string :return: the value of a previously stored define or None if it is not set """ assert key and isinstance(key, str) ban = key + '=' for x in self.env['DEFINES']: if x.startswith(ban): return x[len(ban):] return None @conf def have_define(self, key): """ :param key: define name :type key: string :return: the input key prefixed by *HAVE_* and substitute any invalid characters. :rtype: string """ return (self.env.HAVE_PAT or 'HAVE_%s') % Utils.quote_define_name(key) @conf def write_config_header(self, configfile='', guard='', top=False, env=None, defines=True, headers=False, remove=True, define_prefix=''): """ Write a configuration header containing defines and includes:: def configure(cnf): cnf.define('A', 1) cnf.write_config_header('config.h') :param configfile: relative path to the file to create :type configfile: string :param guard: include guard name to add, by default it is computed from the file name :type guard: string :param top: write the configuration header from the build directory (default is from the current path) :type top: bool :param defines: add the defines (yes by default) :type defines: bool :param headers: add #include in the file :type headers: bool :param remove: remove the defines after they are added (yes by default, works like in autoconf) :type remove: bool :type define_prefix: string :param define_prefix: prefix all the defines in the file with a particular prefix """ # TODO waf 1.8: the parameter env is not used if env: Logs.warn('Cannot pass env to write_config_header') if not configfile: configfile = WAF_CONFIG_H waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile) node = top and self.bldnode or self.path.get_bld() node = node.make_node(configfile) node.parent.mkdir() lst = ['/* WARNING! All changes made to this file will be lost! */\n'] lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard)) lst.append(self.get_config_header(defines, headers, define_prefix=define_prefix)) lst.append('\n#endif /* %s */\n' % waf_guard) node.write('\n'.join(lst)) # config files are not removed on "waf clean" self.env.append_unique(Build.CFG_FILES, [node.abspath()]) if remove: for key in self.env[DEFKEYS]: self.undefine(key) self.env[DEFKEYS] = [] @conf def get_config_header(self, defines=True, headers=False, define_prefix=''): """ Create the contents of a ``config.h`` file from the defines and includes set in conf.env.define_key / conf.env.include_key. No include guards are added. :param defines: write the defines values :type defines: bool :param headers: write the headers :type headers: bool :type define_prefix: string :param define_prefix: prefix all the defines with a particular prefix :return: the contents of a ``config.h`` file :rtype: string """ lst = [] if headers: for x in self.env[INCKEYS]: lst.append('#include <%s>' % x) if defines: for x in self.env[DEFKEYS]: if self.is_defined(x): val = self.get_define(x) lst.append('#define %s %s' % (define_prefix + x, val)) else: lst.append('/* #undef %s */' % (define_prefix + x)) return "\n".join(lst) @conf def cc_add_flags(conf): """ Read the CFLAGS/CPPFLAGS from os.environ and add to conf.env.CFLAGS """ conf.add_os_flags('CPPFLAGS', 'CFLAGS') conf.add_os_flags('CFLAGS') @conf def cxx_add_flags(conf): """ Read the CXXFLAGS/CPPFLAGS and add to conf.env.CXXFLAGS """ conf.add_os_flags('CPPFLAGS', 'CXXFLAGS') conf.add_os_flags('CXXFLAGS') @conf def link_add_flags(conf): """ Read the LINKFLAGS/LDFLAGS and add to conf.env.LDFLAGS """ conf.add_os_flags('LINKFLAGS') conf.add_os_flags('LDFLAGS', 'LINKFLAGS') @conf def cc_load_tools(conf): """ Load the c tool """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('c') @conf def cxx_load_tools(conf): """ Load the cxx tool """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('cxx') @conf def get_cc_version(conf, cc, gcc=False, icc=False): """ Run the preprocessor to determine the compiler version The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env* """ cmd = cc + ['-dM', '-E', '-'] env = conf.env.env or None try: p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env) p.stdin.write('\n'.encode()) out = p.communicate()[0] except Exception: conf.fatal('Could not determine the compiler version %r' % cmd) if not isinstance(out, str): out = out.decode(sys.stdout.encoding or 'iso8859-1') if gcc: if out.find('__INTEL_COMPILER') >= 0: conf.fatal('The intel compiler pretends to be gcc') if out.find('__GNUC__') < 0: conf.fatal('Could not determine the compiler type') if icc and out.find('__INTEL_COMPILER') < 0: conf.fatal('Not icc/icpc') k = {} if icc or gcc: out = out.splitlines() for line in out: lst = shlex.split(line) if len(lst)>2: key = lst[1] val = lst[2] k[key] = val def isD(var): return var in k def isT(var): return var in k and k[var] != '0' # Some documentation is available at http://predef.sourceforge.net # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. if not conf.env.DEST_OS: conf.env.DEST_OS = '' for i in MACRO_TO_DESTOS: if isD(i): conf.env.DEST_OS = MACRO_TO_DESTOS[i] break else: if isD('__APPLE__') and isD('__MACH__'): conf.env.DEST_OS = 'darwin' elif isD('__unix__'): # unix must be tested last as it's a generic fallback conf.env.DEST_OS = 'generic' if isD('__ELF__'): conf.env.DEST_BINFMT = 'elf' elif isD('__WINNT__') or isD('__CYGWIN__'): conf.env.DEST_BINFMT = 'pe' conf.env.LIBDIR = conf.env['PREFIX'] + '/bin' elif isD('__APPLE__'): conf.env.DEST_BINFMT = 'mac-o' if not conf.env.DEST_BINFMT: # Infer the binary format from the os name. conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS) for i in MACRO_TO_DEST_CPU: if isD(i): conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i] break Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) if icc: ver = k['__INTEL_COMPILER'] conf.env['CC_VERSION'] = (ver[:-2], ver[-2], ver[-1]) else: if isD('__clang__'): conf.env['CC_VERSION'] = (k['__clang_major__'], k['__clang_minor__'], k['__clang_patchlevel__']) else: conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) return k @conf def get_xlc_version(conf, cc): """Get the compiler version""" cmd = cc + ['-qversion'] try: out, err = conf.cmd_and_log(cmd, output=0) except Errors.WafError: conf.fatal('Could not find xlc %r' % cmd) # the intention is to catch the 8.0 in "IBM XL C/C++ Enterprise Edition V8.0 for AIX..." for v in (r"IBM XL C/C\+\+.* V(?P\d*)\.(?P\d*)",): version_re = re.compile(v, re.I).search match = version_re(out or err) if match: k = match.groupdict() conf.env['CC_VERSION'] = (k['major'], k['minor']) break else: conf.fatal('Could not determine the XLC version.') # ============ the --as-needed flag should added during the configuration, not at runtime ========= @conf def add_as_needed(self): """ Add ``--as-needed`` to the *LINKFLAGS* """ if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME): self.env.append_unique('LINKFLAGS', '--as-needed') # ============ parallel configuration class cfgtask(Task.TaskBase): """ A task that executes configuration tests make sure that the checks write to conf.env in a thread-safe manner for the moment it only executes conf.check """ def display(self): return '' def runnable_status(self): return Task.RUN_ME def uid(self): return Utils.SIG_NIL def run(self): conf = self.conf bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) bld.env = conf.env bld.init_dirs() bld.in_msg = 1 # suppress top-level start_msg bld.logger = self.logger try: bld.check(**self.args) except Exception: return 1 @conf def multicheck(self, *k, **kw): """ Use tuples to perform parallel configuration tests """ self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k))) class par(object): def __init__(self): self.keep = False self.cache_global = Options.cache_global self.nocache = Options.options.nocache self.returned_tasks = [] self.task_sigs = {} def total(self): return len(tasks) def to_log(self, *k, **kw): return bld = par() tasks = [] for dct in k: x = cfgtask(bld=bld) tasks.append(x) x.args = dct x.bld = bld x.conf = self x.args = dct # bind a logger that will keep the info in memory x.logger = Logs.make_mem_logger(str(id(x)), self.logger) def it(): yield tasks while 1: yield [] p = Runner.Parallel(bld, Options.options.jobs) p.biter = it() p.start() # flush the logs in order into the config.log for x in tasks: x.logger.memhandler.flush() for x in tasks: if x.hasrun != Task.SUCCESS: self.end_msg(kw.get('errmsg', 'no'), color='YELLOW') self.fatal(kw.get('fatalmsg', None) or 'One of the tests has failed, see the config.log for more information') self.end_msg('ok') debian/waf-1.7/waflib/ansiterm.py0000664000000000000000000001763512145745420013730 0ustar import sys, os try: if not (sys.stderr.isatty() and sys.stdout.isatty()): raise ValueError('not a tty') from ctypes import * class COORD(Structure): _fields_ = [("X", c_short), ("Y", c_short)] class SMALL_RECT(Structure): _fields_ = [("Left", c_short), ("Top", c_short), ("Right", c_short), ("Bottom", c_short)] class CONSOLE_SCREEN_BUFFER_INFO(Structure): _fields_ = [("Size", COORD), ("CursorPosition", COORD), ("Attributes", c_short), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] class CONSOLE_CURSOR_INFO(Structure): _fields_ = [('dwSize',c_ulong), ('bVisible', c_int)] sbinfo = CONSOLE_SCREEN_BUFFER_INFO() csinfo = CONSOLE_CURSOR_INFO() hconsole = windll.kernel32.GetStdHandle(-11) windll.kernel32.GetConsoleScreenBufferInfo(hconsole, byref(sbinfo)) if sbinfo.Size.X < 9 or sbinfo.Size.Y < 9: raise ValueError('small console') windll.kernel32.GetConsoleCursorInfo(hconsole, byref(csinfo)) except Exception: pass else: import re, threading is_vista = getattr(sys, "getwindowsversion", None) and sys.getwindowsversion()[0] >= 6 try: _type = unicode except NameError: _type = str to_int = lambda number, default: number and int(number) or default wlock = threading.Lock() STD_OUTPUT_HANDLE = -11 STD_ERROR_HANDLE = -12 class AnsiTerm(object): """ emulate a vt100 terminal in cmd.exe """ def __init__(self): self.encoding = sys.stdout.encoding self.hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) self.cursor_history = [] self.orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() self.orig_csinfo = CONSOLE_CURSOR_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self.orig_sbinfo)) windll.kernel32.GetConsoleCursorInfo(hconsole, byref(self.orig_csinfo)) def screen_buffer_info(self): sbinfo = CONSOLE_SCREEN_BUFFER_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) return sbinfo def clear_line(self, param): mode = param and int(param) or 0 sbinfo = self.screen_buffer_info() if mode == 1: # Clear from begining of line to cursor position line_start = COORD(0, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X elif mode == 2: # Clear entire line line_start = COORD(sbinfo.CursorPosition.X, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X - sbinfo.CursorPosition.X else: # Clear from cursor position to end of line line_start = sbinfo.CursorPosition line_length = sbinfo.Size.X - sbinfo.CursorPosition.X chars_written = c_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_wchar(' '), line_length, line_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, line_length, line_start, byref(chars_written)) def clear_screen(self, param): mode = to_int(param, 0) sbinfo = self.screen_buffer_info() if mode == 1: # Clear from begining of screen to cursor position clear_start = COORD(0, 0) clear_length = sbinfo.CursorPosition.X * sbinfo.CursorPosition.Y elif mode == 2: # Clear entire screen and return cursor to home clear_start = COORD(0, 0) clear_length = sbinfo.Size.X * sbinfo.Size.Y windll.kernel32.SetConsoleCursorPosition(self.hconsole, clear_start) else: # Clear from cursor position to end of screen clear_start = sbinfo.CursorPosition clear_length = ((sbinfo.Size.X - sbinfo.CursorPosition.X) + sbinfo.Size.X * (sbinfo.Size.Y - sbinfo.CursorPosition.Y)) chars_written = c_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_wchar(' '), clear_length, clear_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, clear_length, clear_start, byref(chars_written)) def push_cursor(self, param): sbinfo = self.screen_buffer_info() self.cursor_history.append(sbinfo.CursorPosition) def pop_cursor(self, param): if self.cursor_history: old_pos = self.cursor_history.pop() windll.kernel32.SetConsoleCursorPosition(self.hconsole, old_pos) def set_cursor(self, param): y, sep, x = param.partition(';') x = to_int(x, 1) - 1 y = to_int(y, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), min(max(0, y), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def set_column(self, param): x = to_int(param, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), sbinfo.CursorPosition.Y ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_cursor(self, x_offset=0, y_offset=0): sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, sbinfo.CursorPosition.X + x_offset), sbinfo.Size.X), min(max(0, sbinfo.CursorPosition.Y + y_offset), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_up(self, param): self.move_cursor(y_offset = -to_int(param, 1)) def move_down(self, param): self.move_cursor(y_offset = to_int(param, 1)) def move_left(self, param): self.move_cursor(x_offset = -to_int(param, 1)) def move_right(self, param): self.move_cursor(x_offset = to_int(param, 1)) def next_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = to_int(param, 1) ) def prev_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = -to_int(param, 1) ) def rgb2bgr(self, c): return ((c&1) << 2) | (c&2) | ((c&4)>>2) def set_color(self, param): cols = param.split(';') sbinfo = CONSOLE_SCREEN_BUFFER_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) attr = sbinfo.Attributes for c in cols: if is_vista: c = int(c) else: c = to_int(c, 0) if c in range(30,38): # fgcolor attr = (attr & 0xfff0) | self.rgb2bgr(c-30) elif c in range(40,48): # bgcolor attr = (attr & 0xff0f) | (self.rgb2bgr(c-40) << 4) elif c == 0: # reset attr = self.orig_sbinfo.Attributes elif c == 1: # strong attr |= 0x08 elif c == 4: # blink not available -> bg intensity attr |= 0x80 elif c == 7: # negative attr = (attr & 0xff88) | ((attr & 0x70) >> 4) | ((attr & 0x07) << 4) windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) def show_cursor(self,param): csinfo.bVisible = 1 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) def hide_cursor(self,param): csinfo.bVisible = 0 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) ansi_command_table = { 'A': move_up, 'B': move_down, 'C': move_right, 'D': move_left, 'E': next_line, 'F': prev_line, 'G': set_column, 'H': set_cursor, 'f': set_cursor, 'J': clear_screen, 'K': clear_line, 'h': show_cursor, 'l': hide_cursor, 'm': set_color, 's': push_cursor, 'u': pop_cursor, } # Match either the escape sequence or text not containing escape sequence ansi_tokens = re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') def write(self, text): try: wlock.acquire() for param, cmd, txt in self.ansi_tokens.findall(text): if cmd: cmd_func = self.ansi_command_table.get(cmd) if cmd_func: cmd_func(self, param) else: self.writeconsole(txt) finally: wlock.release() def writeconsole(self, txt): chars_written = c_int() writeconsole = windll.kernel32.WriteConsoleA if isinstance(txt, _type): writeconsole = windll.kernel32.WriteConsoleW TINY_STEP = 3000 for x in range(0, len(txt), TINY_STEP): # According MSDN, size should NOT exceed 64 kb (issue #746) tiny = txt[x : x + TINY_STEP] writeconsole(self.hconsole, tiny, len(tiny), byref(chars_written), None) def flush(self): pass def isatty(self): return True sys.stderr = sys.stdout = AnsiTerm() os.environ['TERM'] = 'vt100' debian/waf-1.7/waflib/Utils.py0000664000000000000000000004005112145745420013172 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Utilities and platform-specific fixes The portability fixes try to provide a consistent behavior of the Waf API through Python versions 2.3 to 3.X and across different platforms (win32, linux, etc) """ import os, sys, errno, traceback, inspect, re, shutil, datetime, gc import subprocess # <- leave this! try: from collections import deque except ImportError: class deque(list): """A deque for Python 2.3 which does not have one""" def popleft(self): return self.pop(0) try: import _winreg as winreg except ImportError: try: import winreg except ImportError: winreg = None from waflib import Errors try: from collections import UserDict except ImportError: from UserDict import UserDict try: from hashlib import md5 except ImportError: try: from md5 import md5 except ImportError: # never fail to enable fixes from another module pass try: import threading except ImportError: class threading(object): """ A fake threading class for platforms lacking the threading module. Use ``waf -j1`` on those platforms """ pass class Lock(object): """Fake Lock class""" def acquire(self): pass def release(self): pass threading.Lock = threading.Thread = Lock else: run_old = threading.Thread.run def run(*args, **kwargs): try: run_old(*args, **kwargs) except (KeyboardInterrupt, SystemExit): raise except Exception: sys.excepthook(*sys.exc_info()) threading.Thread.run = run SIG_NIL = 'iluvcuteoverload'.encode() """Arbitrary null value for a md5 hash. This value must be changed when the hash value is replaced (size)""" O644 = 420 """Constant representing the permissions for regular files (0644 raises a syntax error on python 3)""" O755 = 493 """Constant representing the permissions for executable files (0755 raises a syntax error on python 3)""" rot_chr = ['\\', '|', '/', '-'] "List of characters to use when displaying the throbber (progress bar)" rot_idx = 0 "Index of the current throbber character (progress bar)" try: from collections import defaultdict except ImportError: class defaultdict(dict): """ defaultdict was introduced in python 2.5, so we leave it for python 2.4 and 2.3 """ def __init__(self, default_factory): super(defaultdict, self).__init__() self.default_factory = default_factory def __getitem__(self, key): try: return super(defaultdict, self).__getitem__(key) except KeyError: value = self.default_factory() self[key] = value return value is_win32 = sys.platform in ('win32', 'cli') # we should have put this in the Logs.py file instead :-/ indicator = '\x1b[K%s%s%s\r' if is_win32 and 'NOCOLOR' in os.environ: indicator = '%s%s%s\r' def readf(fname, m='r', encoding='ISO8859-1'): """ Read an entire file into a string, use this function instead of os.open() whenever possible. In practice the wrapper node.read(..) should be preferred to this function:: def build(ctx): from waflib import Utils txt = Utils.readf(self.path.find_node('wscript').abspath()) txt = ctx.path.find_node('wscript').read() :type fname: string :param fname: Path to file :type m: string :param m: Open mode :type encoding: string :param encoding: encoding value, only used for python 3 :rtype: string :return: Content of the file """ if sys.hexversion > 0x3000000 and not 'b' in m: m += 'b' f = open(fname, m) try: txt = f.read() finally: f.close() txt = txt.decode(encoding) else: f = open(fname, m) try: txt = f.read() finally: f.close() return txt def writef(fname, data, m='w', encoding='ISO8859-1'): """ Write an entire file from a string, use this function instead of os.open() whenever possible. In practice the wrapper node.write(..) should be preferred to this function:: def build(ctx): from waflib import Utils txt = Utils.writef(self.path.make_node('i_like_kittens').abspath(), 'some data') self.path.make_node('i_like_kittens').write('some data') :type fname: string :param fname: Path to file :type data: string :param data: The contents to write to the file :type m: string :param m: Open mode :type encoding: string :param encoding: encoding value, only used for python 3 """ if sys.hexversion > 0x3000000 and not 'b' in m: data = data.encode(encoding) m += 'b' f = open(fname, m) try: f.write(data) finally: f.close() def h_file(fname): """ Compute a hash value for a file by using md5. This method may be replaced by a faster version if necessary. The following uses the file size and the timestamp value:: import stat from waflib import Utils def h_file(fname): st = os.stat(fname) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') m = Utils.md5() m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(fname) return m.digest() Utils.h_file = h_file :type fname: string :param fname: path to the file to hash :return: hash of the file contents """ f = open(fname, 'rb') m = md5() try: while fname: fname = f.read(200000) m.update(fname) finally: f.close() return m.digest() if hasattr(os, 'O_NOINHERIT'): def readf_win32(f, m='r', encoding='ISO8859-1'): flags = os.O_NOINHERIT | os.O_RDONLY if 'b' in m: flags |= os.O_BINARY if '+' in m: flags |= os.O_RDWR try: fd = os.open(f, flags) except OSError: raise IOError('Cannot read from %r' % f) if sys.hexversion > 0x3000000 and not 'b' in m: m += 'b' f = os.fdopen(fd, m) try: txt = f.read() finally: f.close() txt = txt.decode(encoding) else: f = os.fdopen(fd, m) try: txt = f.read() finally: f.close() return txt def writef_win32(f, data, m='w', encoding='ISO8859-1'): if sys.hexversion > 0x3000000 and not 'b' in m: data = data.encode(encoding) m += 'b' flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT if 'b' in m: flags |= os.O_BINARY if '+' in m: flags |= os.O_RDWR try: fd = os.open(f, flags) except OSError: raise IOError('Cannot write to %r' % f) f = os.fdopen(fd, m) try: f.write(data) finally: f.close() def h_file_win32(fname): try: fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT) except OSError: raise IOError('Cannot read from %r' % fname) f = os.fdopen(fd, 'rb') m = md5() try: while fname: fname = f.read(200000) m.update(fname) finally: f.close() return m.digest() # replace the default functions readf_old = readf writef_old = writef h_file_old = h_file readf = readf_win32 writef = writef_win32 h_file = h_file_win32 try: x = ''.encode('hex') except LookupError: import binascii def to_hex(s): ret = binascii.hexlify(s) if not isinstance(ret, str): ret = ret.decode('utf-8') return ret else: def to_hex(s): return s.encode('hex') to_hex.__doc__ = """ Return the hexadecimal representation of a string :param s: string to convert :type s: string """ listdir = os.listdir if is_win32: def listdir_win32(s): """ List the contents of a folder in a portable manner. On Win32, return the list of drive letters: ['C:', 'X:', 'Z:'] :type s: string :param s: a string, which can be empty on Windows """ if not s: try: import ctypes except ImportError: # there is nothing much we can do return [x + ':\\' for x in list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')] else: dlen = 4 # length of "?:\\x00" maxdrives = 26 buf = ctypes.create_string_buffer(maxdrives * dlen) ndrives = ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen, ctypes.byref(buf)) return [ str(buf.raw[4*i:4*i+2].decode('ascii')) for i in range(int(ndrives/dlen)) ] if len(s) == 2 and s[1] == ":": s += os.sep if not os.path.isdir(s): e = OSError('%s is not a directory' % s) e.errno = errno.ENOENT raise e return os.listdir(s) listdir = listdir_win32 def num2ver(ver): """ Convert a string, tuple or version number into an integer. The number is supposed to have at most 4 digits:: from waflib.Utils import num2ver num2ver('1.3.2') == num2ver((1,3,2)) == num2ver((1,3,2,0)) :type ver: string or tuple of numbers :param ver: a version number """ if isinstance(ver, str): ver = tuple(ver.split('.')) if isinstance(ver, tuple): ret = 0 for i in range(4): if i < len(ver): ret += 256**(3 - i) * int(ver[i]) return ret return ver def ex_stack(): """ Extract the stack to display exceptions :return: a string represening the last exception """ exc_type, exc_value, tb = sys.exc_info() exc_lines = traceback.format_exception(exc_type, exc_value, tb) return ''.join(exc_lines) def to_list(sth): """ Convert a string argument to a list by splitting on spaces, and pass through a list argument unchanged:: from waflib.Utils import to_list lst = to_list("a b c d") :param sth: List or a string of items separated by spaces :rtype: list :return: Argument converted to list """ if isinstance(sth, str): return sth.split() else: return sth re_nl = re.compile('\r*\n', re.M) def str_to_dict(txt): """ Parse a string with key = value pairs into a dictionary:: from waflib import Utils x = Utils.str_to_dict(''' a = 1 b = test ''') :type s: string :param s: String to parse :rtype: dict :return: Dictionary containing parsed key-value pairs """ tbl = {} lines = re_nl.split(txt) for x in lines: x = x.strip() if not x or x.startswith('#') or x.find('=') < 0: continue tmp = x.split('=') tbl[tmp[0].strip()] = '='.join(tmp[1:]).strip() return tbl def split_path(path): return path.split('/') def split_path_cygwin(path): if path.startswith('//'): ret = path.split('/')[2:] ret[0] = '/' + ret[0] return ret return path.split('/') re_sp = re.compile('[/\\\\]') def split_path_win32(path): if path.startswith('\\\\'): ret = re.split(re_sp, path)[2:] ret[0] = '\\' + ret[0] return ret return re.split(re_sp, path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif is_win32: split_path = split_path_win32 split_path.__doc__ = """ Split a path by / or \\. This function is not like os.path.split :type path: string :param path: path to split :return: list of strings """ def check_dir(path): """ Ensure that a directory exists (similar to ``mkdir -p``). :type dir: string :param dir: Path to directory """ if not os.path.isdir(path): try: os.makedirs(path) except OSError as e: if not os.path.isdir(path): raise Errors.WafError('Cannot create the folder %r' % path, ex=e) def def_attrs(cls, **kw): """ Set default attributes on a class instance :type cls: class :param cls: the class to update the given attributes in. :type kw: dict :param kw: dictionary of attributes names and values. """ for k, v in kw.items(): if not hasattr(cls, k): setattr(cls, k, v) def quote_define_name(s): """ Convert a string to an identifier suitable for C defines. :type s: string :param s: String to convert :rtype: string :return: Identifier suitable for C defines """ fu = re.compile("[^a-zA-Z0-9]").sub("_", s) fu = fu.upper() return fu def h_list(lst): """ Hash lists. For tuples, using hash(tup) is much more efficient :param lst: list to hash :type lst: list of strings :return: hash of the list """ m = md5() m.update(str(lst).encode()) return m.digest() def h_fun(fun): """ Hash functions :param fun: function to hash :type fun: function :return: hash of the function """ try: return fun.code except AttributeError: try: h = inspect.getsource(fun) except IOError: h = "nocode" try: fun.code = h except AttributeError: pass return h reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") def subst_vars(expr, params): """ Replace ${VAR} with the value of VAR taken from a dict or a config set:: from waflib import Utils s = Utils.subst_vars('${PREFIX}/bin', env) :type expr: string :param expr: String to perform substitution on :param params: Dictionary or config set to look up variable values. """ def repl_var(m): if m.group(1): return '\\' if m.group(2): return '$' try: # ConfigSet instances may contain lists return params.get_flat(m.group(3)) except AttributeError: return params[m.group(3)] return reg_subst.sub(repl_var, expr) def destos_to_binfmt(key): """ Return the binary format based on the unversioned platform name. :param key: platform name :type key: string :return: string representing the binary format """ if key == 'darwin': return 'mac-o' elif key in ('win32', 'cygwin', 'uwin', 'msys'): return 'pe' return 'elf' def unversioned_sys_platform(): """ Return the unversioned platform name. Some Python platform names contain versions, that depend on the build environment, e.g. linux2, freebsd6, etc. This returns the name without the version number. Exceptions are os2 and win32, which are returned verbatim. :rtype: string :return: Unversioned platform name """ s = sys.platform if s == 'java': # The real OS is hidden under the JVM. from java.lang import System s = System.getProperty('os.name') # see http://lopica.sourceforge.net/os.html for a list of possible values if s == 'Mac OS X': return 'darwin' elif s.startswith('Windows '): return 'win32' elif s == 'OS/2': return 'os2' elif s == 'HP-UX': return 'hpux' elif s in ('SunOS', 'Solaris'): return 'sunos' else: s = s.lower() # powerpc == darwin for our purposes if s == 'powerpc': return 'darwin' if s == 'win32' or s.endswith('os2') and s != 'sunos2': return s return re.split('\d+$', s)[0] def nada(*k, **kw): """ A function that does nothing :return: None """ pass class Timer(object): """ Simple object for timing the execution of commands. Its string representation is the current time:: from waflib.Utils import Timer timer = Timer() a_few_operations() s = str(timer) """ def __init__(self): self.start_time = datetime.datetime.utcnow() def __str__(self): delta = datetime.datetime.utcnow() - self.start_time days = int(delta.days) hours = delta.seconds // 3600 minutes = (delta.seconds - hours * 3600) // 60 seconds = delta.seconds - hours * 3600 - minutes * 60 + float(delta.microseconds) / 1000 / 1000 result = '' if days: result += '%dd' % days if days or hours: result += '%dh' % hours if days or hours or minutes: result += '%dm' % minutes return '%s%.3fs' % (result, seconds) if is_win32: old = shutil.copy2 def copy2(src, dst): """ shutil.copy2 does not copy the file attributes on windows, so we hack into the shutil module to fix the problem """ old(src, dst) shutil.copystat(src, dst) setattr(shutil, 'copy2', copy2) if os.name == 'java': # Jython cannot disable the gc but they can enable it ... wtf? try: gc.disable() gc.enable() except NotImplementedError: gc.disable = gc.enable def read_la_file(path): """ Read property files, used by msvc.py :param path: file to read :type path: string """ sp = re.compile(r'^([^=]+)=\'(.*)\'$') dc = {} for line in readf(path).splitlines(): try: _, left, right, _ = sp.split(line.strip()) dc[left] = right except ValueError: pass return dc def nogc(fun): """ Decorator: let a function disable the garbage collector during its execution. It is used in the build context when storing/loading the build cache file (pickle) :param fun: function to execute :type fun: function :return: the return value of the function executed """ def f(*k, **kw): try: gc.disable() ret = fun(*k, **kw) finally: gc.enable() return ret f.__doc__ = fun.__doc__ return f def run_once(fun): """ Decorator: let a function cache its results, use like this:: @run_once def foo(k): return 345*2343 :param fun: function to execute :type fun: function :return: the return value of the function executed """ cache = {} def wrap(k): try: return cache[k] except KeyError: ret = fun(k) cache[k] = ret return ret wrap.__cache__ = cache return wrap def get_registry_app_path(key, filename): if not winreg: return None try: result = winreg.QueryValue(key, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe" % filename[0]) except WindowsError: pass else: if os.path.isfile(result): return result debian/waf-1.7/waflib/__init__.py0000664000000000000000000000010712145745420013627 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.7/waflib/Build.py0000664000000000000000000011207212145745420013134 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Classes related to the build phase (build, clean, install, step, etc) The inheritance tree is the following: """ import os, sys, errno, re, shutil try: import cPickle except ImportError: import pickle as cPickle from waflib import Runner, TaskGen, Utils, ConfigSet, Task, Logs, Options, Context, Errors import waflib.Node CACHE_DIR = 'c4che' """Location of the cache files""" CACHE_SUFFIX = '_cache.py' """Suffix for the cache files""" INSTALL = 1337 """Positive value '->' install, see :py:attr:`waflib.Build.BuildContext.is_install`""" UNINSTALL = -1337 """Negative value '<-' uninstall, see :py:attr:`waflib.Build.BuildContext.is_install`""" SAVED_ATTRS = 'root node_deps raw_deps task_sigs'.split() """Build class members to save between the runs (root, node_deps, raw_deps, task_sigs)""" CFG_FILES = 'cfg_files' """Files from the build directory to hash before starting the build (``config.h`` written during the configuration)""" POST_AT_ONCE = 0 """Post mode: all task generators are posted before the build really starts""" POST_LAZY = 1 """Post mode: post the task generators group after group""" POST_BOTH = 2 """Post mode: post the task generators at once, then re-check them for each group""" class BuildContext(Context.Context): '''executes the build''' cmd = 'build' variant = '' def __init__(self, **kw): super(BuildContext, self).__init__(**kw) self.is_install = 0 """Non-zero value when installing or uninstalling file""" self.top_dir = kw.get('top_dir', Context.top_dir) self.run_dir = kw.get('run_dir', Context.run_dir) self.post_mode = POST_AT_ONCE """post the task generators at once, group-by-group, or both""" # output directory - may be set until the nodes are considered self.out_dir = kw.get('out_dir', Context.out_dir) self.cache_dir = kw.get('cache_dir', None) if not self.cache_dir: self.cache_dir = self.out_dir + os.sep + CACHE_DIR # map names to environments, the '' must be defined self.all_envs = {} # ======================================= # # cache variables self.task_sigs = {} """Signatures of the tasks (persists between build executions)""" self.node_deps = {} """Dict of node dependencies found by :py:meth:`waflib.Task.Task.scan` (persists between build executions)""" self.raw_deps = {} """Dict of custom data returned by :py:meth:`waflib.Task.Task.scan` (persists between build executions)""" # list of folders that are already scanned # so that we do not need to stat them one more time self.cache_dir_contents = {} self.task_gen_cache_names = {} self.launch_dir = Context.launch_dir self.jobs = Options.options.jobs self.targets = Options.options.targets self.keep = Options.options.keep self.cache_global = Options.cache_global self.nocache = Options.options.nocache self.progress_bar = Options.options.progress_bar ############ stuff below has not been reviewed # Manual dependencies. self.deps_man = Utils.defaultdict(list) """Manual dependencies set by :py:meth:`waflib.Build.BuildContext.add_manual_dependency`""" # just the structure here self.current_group = 0 """ Current build group """ self.groups = [] """ List containing lists of task generators """ self.group_names = {} """ Map group names to the group lists. See :py:meth:`waflib.Build.BuildContext.add_group` """ def get_variant_dir(self): """Getter for the variant_dir attribute""" if not self.variant: return self.out_dir return os.path.join(self.out_dir, self.variant) variant_dir = property(get_variant_dir, None) def __call__(self, *k, **kw): """ Create a task generator and add it to the current build group. The following forms are equivalent:: def build(bld): tg = bld(a=1, b=2) def build(bld): tg = bld() tg.a = 1 tg.b = 2 def build(bld): tg = TaskGen.task_gen(a=1, b=2) bld.add_to_group(tg, None) :param group: group name to add the task generator to :type group: string """ kw['bld'] = self ret = TaskGen.task_gen(*k, **kw) self.task_gen_cache_names = {} # reset the cache, each time self.add_to_group(ret, group=kw.get('group', None)) return ret def rule(self, *k, **kw): """ Wrapper for creating a task generator using the decorator notation. The the following code: @bld.rule( target = "foo" ) def _(tsk): print("bar") is equivalent to: def bar(tsk): print("bar") bld( target = "foo", rule = bar, ) """ def f(rule): ret = self(*k, **kw) ret.rule = rule return ret return f def __copy__(self): """Implemented to prevents copies of build contexts (raises an exception)""" raise Errors.WafError('build contexts are not supposed to be copied') def install_files(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.install_files`""" pass def install_as(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.install_as`""" pass def symlink_as(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.symlink_as`""" pass def load_envs(self): """ The configuration command creates files of the form ``build/c4che/NAMEcache.py``. This method creates a :py:class:`waflib.ConfigSet.ConfigSet` instance for each ``NAME`` by reading those files. The config sets are then stored in the dict :py:attr:`waflib.Build.BuildContext.allenvs`. """ node = self.root.find_node(self.cache_dir) if not node: raise Errors.WafError('The project was not configured: run "waf configure" first!') lst = node.ant_glob('**/*%s' % CACHE_SUFFIX, quiet=True) if not lst: raise Errors.WafError('The cache directory is empty: reconfigure the project') for x in lst: name = x.path_from(node).replace(CACHE_SUFFIX, '').replace('\\', '/') env = ConfigSet.ConfigSet(x.abspath()) self.all_envs[name] = env for f in env[CFG_FILES]: newnode = self.root.find_resource(f) try: h = Utils.h_file(newnode.abspath()) except (IOError, AttributeError): Logs.error('cannot find %r' % f) h = Utils.SIG_NIL newnode.sig = h def init_dirs(self): """ Initialize the project directory and the build directory by creating the nodes :py:attr:`waflib.Build.BuildContext.srcnode` and :py:attr:`waflib.Build.BuildContext.bldnode` corresponding to ``top_dir`` and ``variant_dir`` respectively. The ``bldnode`` directory will be created if it does not exist. """ if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') self.path = self.srcnode = self.root.find_dir(self.top_dir) self.bldnode = self.root.make_node(self.variant_dir) self.bldnode.mkdir() def execute(self): """ Restore the data from previous builds and call :py:meth:`waflib.Build.BuildContext.execute_build`. Overrides from :py:func:`waflib.Context.Context.execute` """ self.restore() if not self.all_envs: self.load_envs() self.execute_build() def execute_build(self): """ Execute the build by: * reading the scripts (see :py:meth:`waflib.Context.Context.recurse`) * calling :py:meth:`waflib.Build.BuildContext.pre_build` to call user build functions * calling :py:meth:`waflib.Build.BuildContext.compile` to process the tasks * calling :py:meth:`waflib.Build.BuildContext.post_build` to call user build functions """ Logs.info("Waf: Entering directory `%s'" % self.variant_dir) self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() if self.progress_bar: sys.stderr.write(Logs.colors.cursor_off) try: self.compile() finally: if self.progress_bar == 1: c = len(self.returned_tasks) or 1 self.to_log(self.progress_line(c, c, Logs.colors.BLUE, Logs.colors.NORMAL)) print('') sys.stdout.flush() sys.stderr.write(Logs.colors.cursor_on) Logs.info("Waf: Leaving directory `%s'" % self.variant_dir) self.post_build() def restore(self): """ Load the data from a previous run, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS` """ try: env = ConfigSet.ConfigSet(os.path.join(self.cache_dir, 'build.config.py')) except (IOError, OSError): pass else: if env['version'] < Context.HEXVERSION: raise Errors.WafError('Version mismatch! reconfigure the project') for t in env['tools']: self.setup(**t) dbfn = os.path.join(self.variant_dir, Context.DBFILE) try: data = Utils.readf(dbfn, 'rb') except (IOError, EOFError): # handle missing file/empty file Logs.debug('build: Could not load the build cache %s (missing)' % dbfn) else: try: waflib.Node.pickle_lock.acquire() waflib.Node.Nod3 = self.node_class try: data = cPickle.loads(data) except Exception as e: Logs.debug('build: Could not pickle the build cache %s: %r' % (dbfn, e)) else: for x in SAVED_ATTRS: setattr(self, x, data[x]) finally: waflib.Node.pickle_lock.release() self.init_dirs() def store(self): """ Store the data for next runs, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS`. Uses a temporary file to avoid problems on ctrl+c. """ data = {} for x in SAVED_ATTRS: data[x] = getattr(self, x) db = os.path.join(self.variant_dir, Context.DBFILE) try: waflib.Node.pickle_lock.acquire() waflib.Node.Nod3 = self.node_class x = cPickle.dumps(data, -1) finally: waflib.Node.pickle_lock.release() Utils.writef(db + '.tmp', x, m='wb') try: st = os.stat(db) os.unlink(db) if not Utils.is_win32: # win32 has no chown but we're paranoid os.chown(db + '.tmp', st.st_uid, st.st_gid) except (AttributeError, OSError): pass # do not use shutil.move (copy is not thread-safe) os.rename(db + '.tmp', db) def compile(self): """ Run the build by creating an instance of :py:class:`waflib.Runner.Parallel` The cache file is not written if the build is up to date (no task executed). """ Logs.debug('build: compile()') # use another object to perform the producer-consumer logic (reduce the complexity) self.producer = Runner.Parallel(self, self.jobs) self.producer.biter = self.get_build_iterator() self.returned_tasks = [] # not part of the API yet try: self.producer.start() except KeyboardInterrupt: self.store() raise else: if self.producer.dirty: self.store() if self.producer.error: raise Errors.BuildError(self.producer.error) def setup(self, tool, tooldir=None, funs=None): """ Import waf tools, used to import those accessed during the configuration:: def configure(conf): conf.load('glib2') def build(bld): pass # glib2 is imported implicitly :param tool: tool list :type tool: list :param tooldir: optional tool directory (sys.path) :type tooldir: list of string :param funs: unused variable """ if isinstance(tool, list): for i in tool: self.setup(i, tooldir) return module = Context.load_tool(tool, tooldir) if hasattr(module, "setup"): module.setup(self) def get_env(self): """Getter for the env property""" try: return self.all_envs[self.variant] except KeyError: return self.all_envs[''] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def add_manual_dependency(self, path, value): """ Adds a dependency from a node object to a value:: def build(bld): bld.add_manual_dependency( bld.path.find_resource('wscript'), bld.root.find_resource('/etc/fstab')) :param path: file path :type path: string or :py:class:`waflib.Node.Node` :param value: value to depend on :type value: :py:class:`waflib.Node.Node`, string, or function returning a string """ if path is None: raise ValueError('Invalid input') if isinstance(path, waflib.Node.Node): node = path elif os.path.isabs(path): node = self.root.find_resource(path) else: node = self.path.find_resource(path) if isinstance(value, list): self.deps_man[id(node)].extend(value) else: self.deps_man[id(node)].append(value) def launch_node(self): """Returns the launch directory as a :py:class:`waflib.Node.Node` object""" try: # private cache return self.p_ln except AttributeError: self.p_ln = self.root.find_dir(self.launch_dir) return self.p_ln def hash_env_vars(self, env, vars_lst): """ Hash configuration set variables:: def build(bld): bld.hash_env_vars(bld.env, ['CXX', 'CC']) :param env: Configuration Set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param vars_lst: list of variables :type vars_list: list of string """ if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [env[a] for a in vars_lst] ret = Utils.h_list(lst) Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) cache[idx] = ret return ret def get_tgen_by_name(self, name): """ Retrieves a task generator from its name or its target name the name must be unique:: def build(bld): tg = bld(name='foo') tg == bld.get_tgen_by_name('foo') """ cache = self.task_gen_cache_names if not cache: # create the index lazily for g in self.groups: for tg in g: try: cache[tg.name] = tg except AttributeError: # raised if not a task generator, which should be uncommon pass try: return cache[name] except KeyError: raise Errors.WafError('Could not find a task generator for the name %r' % name) def progress_line(self, state, total, col1, col2): """ Compute the progress bar used by ``waf -p`` """ n = len(str(total)) Utils.rot_idx += 1 ind = Utils.rot_chr[Utils.rot_idx % 4] pc = (100.*state)/total eta = str(self.timer) fs = "[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s][" % (n, n, ind) left = fs % (state, total, col1, pc, col2) right = '][%s%s%s]' % (col1, eta, col2) cols = Logs.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) if cols < 7: cols = 7 ratio = ((cols*state)//total) - 1 bar = ('='*ratio+'>').ljust(cols) msg = Utils.indicator % (left, bar, right) return msg def declare_chain(self, *k, **kw): """ Wrapper for :py:func:`waflib.TaskGen.declare_chain` provided for convenience """ return TaskGen.declare_chain(*k, **kw) def pre_build(self): """Execute user-defined methods before the build starts, see :py:meth:`waflib.Build.BuildContext.add_pre_fun`""" for m in getattr(self, 'pre_funs', []): m(self) def post_build(self): """Executes the user-defined methods after the build is successful, see :py:meth:`waflib.Build.BuildContext.add_post_fun`""" for m in getattr(self, 'post_funs', []): m(self) def add_pre_fun(self, meth): """ Bind a method to execute after the scripts are read and before the build starts:: def mycallback(bld): print("Hello, world!") def build(bld): bld.add_pre_fun(mycallback) """ try: self.pre_funs.append(meth) except AttributeError: self.pre_funs = [meth] def add_post_fun(self, meth): """ Bind a method to execute immediately after the build is successful:: def call_ldconfig(bld): bld.exec_command('/sbin/ldconfig') def build(bld): if bld.cmd == 'install': bld.add_pre_fun(call_ldconfig) """ try: self.post_funs.append(meth) except AttributeError: self.post_funs = [meth] def get_group(self, x): """ Get the group x, or return the current group if x is None :param x: name or number or None :type x: string, int or None """ if not self.groups: self.add_group() if x is None: return self.groups[self.current_group] if x in self.group_names: return self.group_names[x] return self.groups[x] def add_to_group(self, tgen, group=None): """add a task or a task generator for the build""" # paranoid assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.TaskBase)) tgen.bld = self self.get_group(group).append(tgen) def get_group_name(self, g): """name for the group g (utility)""" if not isinstance(g, list): g = self.groups[g] for x in self.group_names: if id(self.group_names[x]) == id(g): return x return '' def get_group_idx(self, tg): """ Index of the group containing the task generator given as argument:: def build(bld): tg = bld(name='nada') 0 == bld.get_group_idx(tg) :param tg: Task generator object :type tg: :py:class:`waflib.TaskGen.task_gen` """ se = id(tg) for i in range(len(self.groups)): for t in self.groups[i]: if id(t) == se: return i return None def add_group(self, name=None, move=True): """ Add a new group of tasks/task generators. By default the new group becomes the default group for new task generators. :param name: name for this group :type name: string :param move: set the group created as default group (True by default) :type move: bool """ #if self.groups and not self.groups[0].tasks: # error('add_group: an empty group is already present') if name and name in self.group_names: Logs.error('add_group: name %s already present' % name) g = [] self.group_names[name] = g self.groups.append(g) if move: self.current_group = len(self.groups) - 1 def set_group(self, idx): """ Set the current group to be idx: now new task generators will be added to this group by default:: def build(bld): bld(rule='touch ${TGT}', target='foo.txt') bld.add_group() # now the current group is 1 bld(rule='touch ${TGT}', target='bar.txt') bld.set_group(0) # now the current group is 0 bld(rule='touch ${TGT}', target='truc.txt') # build truc.txt before bar.txt :param idx: group name or group index :type idx: string or int """ if isinstance(idx, str): g = self.group_names[idx] for i in range(len(self.groups)): if id(g) == id(self.groups[i]): self.current_group = i else: self.current_group = idx def total(self): """ Approximate task count: this value may be inaccurate if task generators are posted lazily (see :py:attr:`waflib.Build.BuildContext.post_mode`). The value :py:attr:`waflib.Runner.Parallel.total` is updated during the task execution. """ total = 0 for group in self.groups: for tg in group: try: total += len(tg.tasks) except AttributeError: total += 1 return total def get_targets(self): """ Return the task generator corresponding to the 'targets' list, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator`:: $ waf --targets=myprogram,myshlib """ to_post = [] min_grp = 0 for name in self.targets.split(','): tg = self.get_tgen_by_name(name) if not tg: raise Errors.WafError('target %r does not exist' % name) m = self.get_group_idx(tg) if m > min_grp: min_grp = m to_post = [tg] elif m == min_grp: to_post.append(tg) return (min_grp, to_post) def get_all_task_gen(self): """ Utility method, returns a list of all task generators - if you need something more complicated, implement your own """ lst = [] for g in self.groups: lst.extend(g) return lst def post_group(self): """ Post the task generators from the group indexed by self.cur, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ if self.targets == '*': for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: f() elif self.targets: if self.cur < self._min_grp: for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: f() else: for tg in self._exact_tg: tg.post() else: ln = self.launch_node() if ln.is_child_of(self.bldnode): Logs.warn('Building from the build directory, forcing --targets=*') ln = self.srcnode elif not ln.is_child_of(self.srcnode): Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)' % (ln.abspath(), self.srcnode.abspath())) ln = self.srcnode for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: if tg.path.is_child_of(ln): f() def get_tasks_group(self, idx): """ Return all the tasks for the group of num idx, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ tasks = [] for tg in self.groups[idx]: try: tasks.extend(tg.tasks) except AttributeError: # not a task generator, can be the case for installation tasks tasks.append(tg) return tasks def get_build_iterator(self): """ Creates a generator object that returns lists of tasks executable in parallel (yield) :return: tasks which can be executed immediatly :rtype: list of :py:class:`waflib.Task.TaskBase` """ self.cur = 0 if self.targets and self.targets != '*': (self._min_grp, self._exact_tg) = self.get_targets() global lazy_post if self.post_mode != POST_LAZY: while self.cur < len(self.groups): self.post_group() self.cur += 1 self.cur = 0 while self.cur < len(self.groups): # first post the task generators for the group if self.post_mode != POST_AT_ONCE: self.post_group() # then extract the tasks tasks = self.get_tasks_group(self.cur) # if the constraints are set properly (ext_in/ext_out, before/after) # the call to set_file_constraints may be removed (can be a 15% penalty on no-op rebuilds) # (but leave set_file_constraints for the installation step) # # if the tasks have only files, set_file_constraints is required but set_precedence_constraints is not necessary # Task.set_file_constraints(tasks) Task.set_precedence_constraints(tasks) self.cur_tasks = tasks self.cur += 1 if not tasks: # return something else the build will stop continue yield tasks while 1: yield [] #def install_dir(self, path, env=None): # """ # Create empty folders for the installation (very rarely used) TODO # """ # return class inst(Task.Task): """ Special task used for installing files and symlinks, it behaves both like a task and like a task generator """ color = 'CYAN' def uid(self): lst = [self.dest, self.path] + self.source return Utils.h_list(repr(lst)) def post(self): """ Same interface as in :py:meth:`waflib.TaskGen.task_gen.post` """ buf = [] for x in self.source: if isinstance(x, waflib.Node.Node): y = x else: y = self.path.find_resource(x) if not y: if Logs.verbose: Logs.warn('Could not find %s immediately (may cause broken builds)' % x) idx = self.generator.bld.get_group_idx(self) for tg in self.generator.bld.groups[idx]: if not isinstance(tg, inst) and id(tg) != id(self): tg.post() y = self.path.find_resource(x) if y: break else: raise Errors.WafError('Could not find %r in %r' % (x, self.path)) buf.append(y) self.inputs = buf def runnable_status(self): """ Installation tasks are always executed, so this method returns either :py:const:`waflib.Task.ASK_LATER` or :py:const:`waflib.Task.RUN_ME`. """ ret = super(inst, self).runnable_status() if ret == Task.SKIP_ME: return Task.RUN_ME return ret def __str__(self): """Return an empty string to disable the display""" return '' def run(self): """The attribute 'exec_task' holds the method to execute""" return self.generator.exec_task() def get_install_path(self, destdir=True): """ Installation path obtained from ``self.dest`` and prefixed by the destdir. The variables such as '${PREFIX}/bin' are substituted. """ dest = Utils.subst_vars(self.dest, self.env) dest = dest.replace('/', os.sep) if destdir and Options.options.destdir: dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) return dest def exec_install_files(self): """ Predefined method for installing files """ destpath = self.get_install_path() if not destpath: raise Errors.WafError('unknown installation path %r' % self.generator) for x, y in zip(self.source, self.inputs): if self.relative_trick: destfile = os.path.join(destpath, y.path_from(self.path)) Utils.check_dir(os.path.dirname(destfile)) else: destfile = os.path.join(destpath, y.name) self.generator.bld.do_install(y.abspath(), destfile, self.chmod) def exec_install_as(self): """ Predefined method for installing one file with a given name """ destfile = self.get_install_path() self.generator.bld.do_install(self.inputs[0].abspath(), destfile, self.chmod) def exec_symlink_as(self): """ Predefined method for installing a symlink """ destfile = self.get_install_path() src = self.link if self.relative_trick: src = os.path.relpath(src, os.path.dirname(destfile)) self.generator.bld.do_link(src, destfile) class InstallContext(BuildContext): '''installs the targets on the system''' cmd = 'install' def __init__(self, **kw): super(InstallContext, self).__init__(**kw) # list of targets to uninstall for removing the empty folders after uninstalling self.uninstall = [] self.is_install = INSTALL def do_install(self, src, tgt, chmod=Utils.O644): """ Copy a file from src to tgt with given file permissions. The actual copy is not performed if the source and target file have the same size and the same timestamps. When the copy occurs, the file is first removed and then copied (prevent stale inodes). This method is overridden in :py:meth:`waflib.Build.UninstallContext.do_install` to remove the file. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string :param chmod: installation mode :type chmod: int """ d, _ = os.path.split(tgt) if not d: raise Errors.WafError('Invalid installation given %r->%r' % (src, tgt)) Utils.check_dir(d) srclbl = src.replace(self.srcnode.abspath() + os.sep, '') if not Options.options.force: # check if the file is already there to avoid a copy try: st1 = os.stat(tgt) st2 = os.stat(src) except OSError: pass else: # same size and identical timestamps -> make no copy if st1.st_mtime + 2 >= st2.st_mtime and st1.st_size == st2.st_size: if not self.progress_bar: Logs.info('- install %s (from %s)' % (tgt, srclbl)) return False if not self.progress_bar: Logs.info('+ install %s (from %s)' % (tgt, srclbl)) # following is for shared libs and stale inodes (-_-) try: os.remove(tgt) except OSError: pass try: shutil.copy2(src, tgt) os.chmod(tgt, chmod) except IOError: try: os.stat(src) except (OSError, IOError): Logs.error('File %r does not exist' % src) raise Errors.WafError('Could not install the file %r' % tgt) def do_link(self, src, tgt): """ Create a symlink from tgt to src. This method is overridden in :py:meth:`waflib.Build.UninstallContext.do_link` to remove the symlink. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string """ d, _ = os.path.split(tgt) Utils.check_dir(d) link = False if not os.path.islink(tgt): link = True elif os.readlink(tgt) != src: link = True if link: try: os.remove(tgt) except OSError: pass if not self.progress_bar: Logs.info('+ symlink %s (to %s)' % (tgt, src)) os.symlink(src, tgt) else: if not self.progress_bar: Logs.info('- symlink %s (to %s)' % (tgt, src)) def run_task_now(self, tsk, postpone): """ This method is called by :py:meth:`waflib.Build.InstallContext.install_files`, :py:meth:`waflib.Build.InstallContext.install_as` and :py:meth:`waflib.Build.InstallContext.symlink_as` immediately after the installation task is created. Its role is to force the immediate execution if necessary, that is when ``postpone=False`` was given. """ tsk.post() if not postpone: if tsk.runnable_status() == Task.ASK_LATER: raise self.WafError('cannot post the task %r' % tsk) tsk.run() def install_files(self, dest, files, env=None, chmod=Utils.O644, relative_trick=False, cwd=None, add=True, postpone=True): """ Create a task to install files on the system:: def build(bld): bld.install_files('${DATADIR}', self.path.find_resource('wscript')) :param dest: absolute path of the destination directory :type dest: string :param files: input files :type files: list of strings or list of nodes :param env: configuration set for performing substitutions in dest :type env: Configuration set :param relative_trick: preserve the folder hierarchy when installing whole folders :type relative_trick: bool :param cwd: parent node for searching srcfile, when srcfile is not a :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool """ tsk = inst(env=env or self.env) tsk.bld = self tsk.path = cwd or self.path tsk.chmod = chmod if isinstance(files, waflib.Node.Node): tsk.source = [files] else: tsk.source = Utils.to_list(files) tsk.dest = dest tsk.exec_task = tsk.exec_install_files tsk.relative_trick = relative_trick if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk def install_as(self, dest, srcfile, env=None, chmod=Utils.O644, cwd=None, add=True, postpone=True): """ Create a task to install a file on the system with a different name:: def build(bld): bld.install_as('${PREFIX}/bin', 'myapp', chmod=Utils.O755) :param dest: absolute path of the destination file :type dest: string :param srcfile: input file :type srcfile: string or node :param cwd: parent node for searching srcfile, when srcfile is not a :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param env: configuration set for performing substitutions in dest :type env: Configuration set :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool """ tsk = inst(env=env or self.env) tsk.bld = self tsk.path = cwd or self.path tsk.chmod = chmod tsk.source = [srcfile] tsk.dest = dest tsk.exec_task = tsk.exec_install_as if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk def symlink_as(self, dest, src, env=None, cwd=None, add=True, postpone=True, relative_trick=False): """ Create a task to install a symlink:: def build(bld): bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') :param dest: absolute path of the symlink :type dest: string :param src: absolute or relative path of the link :type src: string :param env: configuration set for performing substitutions in dest :type env: Configuration set :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool :param relative_trick: make the symlink relative (default: ``False``) :type relative_trick: bool """ if Utils.is_win32: # symlinks *cannot* work on that platform return tsk = inst(env=env or self.env) tsk.bld = self tsk.dest = dest tsk.path = cwd or self.path tsk.source = [] tsk.link = src tsk.relative_trick = relative_trick tsk.exec_task = tsk.exec_symlink_as if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk class UninstallContext(InstallContext): '''removes the targets installed''' cmd = 'uninstall' def __init__(self, **kw): super(UninstallContext, self).__init__(**kw) self.is_install = UNINSTALL def do_install(self, src, tgt, chmod=Utils.O644): """See :py:meth:`waflib.Build.InstallContext.do_install`""" if not self.progress_bar: Logs.info('- remove %s' % tgt) self.uninstall.append(tgt) try: os.remove(tgt) except OSError as e: if e.errno != errno.ENOENT: if not getattr(self, 'uninstall_error', None): self.uninstall_error = True Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') if Logs.verbose > 1: Logs.warn('Could not remove %s (error code %r)' % (e.filename, e.errno)) # TODO ita refactor this into a post build action to uninstall the folders (optimization) while tgt: tgt = os.path.dirname(tgt) try: os.rmdir(tgt) except OSError: break def do_link(self, src, tgt): """See :py:meth:`waflib.Build.InstallContext.do_link`""" try: if not self.progress_bar: Logs.info('- unlink %s' % tgt) os.remove(tgt) except OSError: pass # TODO ita refactor this into a post build action to uninstall the folders (optimization)? while tgt: tgt = os.path.dirname(tgt) try: os.rmdir(tgt) except OSError: break def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ try: # do not execute any tasks def runnable_status(self): return Task.SKIP_ME setattr(Task.Task, 'runnable_status_back', Task.Task.runnable_status) setattr(Task.Task, 'runnable_status', runnable_status) super(UninstallContext, self).execute() finally: setattr(Task.Task, 'runnable_status', Task.Task.runnable_status_back) class CleanContext(BuildContext): '''cleans the project''' cmd = 'clean' def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) try: self.clean() finally: self.store() def clean(self): """Remove files from the build directory if possible, and reset the caches""" Logs.debug('build: clean called') if self.bldnode != self.srcnode: # would lead to a disaster if top == out lst=[] for e in self.all_envs.values(): lst.extend(self.root.find_or_declare(f) for f in e[CFG_FILES]) for n in self.bldnode.ant_glob('**/*', excl='.lock* *conf_check_*/** config.log c4che/*', quiet=True): if n in lst: continue n.delete() self.root.children = {} for v in 'node_deps task_sigs raw_deps'.split(): setattr(self, v, {}) class ListContext(BuildContext): '''lists the targets to execute''' cmd = 'list' def execute(self): """ See :py:func:`waflib.Context.Context.execute`. """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() try: # force the cache initialization self.get_tgen_by_name('') except Exception: pass lst = list(self.task_gen_cache_names.keys()) lst.sort() for k in lst: Logs.pprint('GREEN', k) class StepContext(BuildContext): '''executes tasks in a step-by-step fashion, for debugging''' cmd = 'step' def __init__(self, **kw): super(StepContext, self).__init__(**kw) self.files = Options.options.files def compile(self): """ Compile the tasks matching the input/output files given (regular expression matching). Derived from :py:meth:`waflib.Build.BuildContext.compile`:: $ waf step --files=foo.c,bar.c,in:truc.c,out:bar.o $ waf step --files=in:foo.cpp.1.o # link task only """ if not self.files: Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') BuildContext.compile(self) return targets = None if self.targets and self.targets != '*': targets = self.targets.split(',') for g in self.groups: for tg in g: if targets and tg.name not in targets: continue try: f = tg.post except AttributeError: pass else: f() for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.TaskBase): lst = [tg] else: lst = tg.tasks for tsk in lst: do_exec = False for node in getattr(tsk, 'inputs', []): if matcher(node, output=False): do_exec = True break for node in getattr(tsk, 'outputs', []): if matcher(node, output=True): do_exec = True break if do_exec: ret = tsk.run() Logs.info('%s -> exit %r' % (str(tsk), ret)) def get_matcher(self, pat): # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output == True and not out: return False if output == False and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match BuildContext.store = Utils.nogc(BuildContext.store) BuildContext.restore = Utils.nogc(BuildContext.restore) debian/waf-1.7/waflib/ConfigSet.py0000664000000000000000000001737112145745420013764 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ ConfigSet: a special dict The values put in :py:class:`ConfigSet` must be lists """ import copy, re, os from waflib import Logs, Utils re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) class ConfigSet(object): """ A dict that honor serialization and parent relationships. The serialization format is human-readable (python-like) and performed by using eval() and repr(). For high performance prefer pickle. Do not store functions as they are not serializable. The values can be accessed by attributes or by keys:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.FOO = 'test' env['FOO'] = 'test' """ __slots__ = ('table', 'parent') def __init__(self, filename=None): self.table = {} """ Internal dict holding the object values """ #self.parent = None if filename: self.load(filename) def __contains__(self, key): """ Enable the *in* syntax:: if 'foo' in env: print env['foo'] """ if key in self.table: return True try: return self.parent.__contains__(key) except AttributeError: return False # parent may not exist def keys(self): """Dict interface (unknown purpose)""" keys = set() cur = self while cur: keys.update(cur.table.keys()) cur = getattr(cur, 'parent', None) keys = list(keys) keys.sort() return keys def __str__(self): """Text representation of the ConfigSet (for debugging purposes)""" return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in self.keys()]) def __getitem__(self, key): """ Dictionary interface: get value from key:: def configure(conf): conf.env['foo'] = {} print(env['foo']) """ try: while 1: x = self.table.get(key, None) if not x is None: return x self = self.parent except AttributeError: return [] def __setitem__(self, key, value): """ Dictionary interface: get value from key """ self.table[key] = value def __delitem__(self, key): """ Dictionary interface: get value from key """ self[key] = [] def __getattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value conf.env['value'] """ if name in self.__slots__: return object.__getattr__(self, name) else: return self[name] def __setattr__(self, name, value): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value = x env['value'] = x """ if name in self.__slots__: object.__setattr__(self, name, value) else: self[name] = value def __delattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): del env.value del env['value'] """ if name in self.__slots__: object.__delattr__(self, name) else: del self[name] def derive(self): """ Returns a new ConfigSet deriving from self. The copy returned will be a shallow copy:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.append_value('CFLAGS', ['-O2']) child = env.derive() child.CFLAGS.append('test') # warning! this will modify 'env' child.CFLAGS = ['-O3'] # new list, ok child.append_value('CFLAGS', ['-O3']) # ok Use :py:func:`ConfigSet.detach` to detach the child from the parent. """ newenv = ConfigSet() newenv.parent = self return newenv def detach(self): """ Detach self from its parent (if existing) Modifying the parent :py:class:`ConfigSet` will not change the current object Modifying this :py:class:`ConfigSet` will not modify the parent one. """ tbl = self.get_merged_dict() try: delattr(self, 'parent') except AttributeError: pass else: keys = tbl.keys() for x in keys: tbl[x] = copy.deepcopy(tbl[x]) self.table = tbl def get_flat(self, key): """ Return a value as a string. If the input is a list, the value returned is space-separated. :param key: key to use :type key: string """ s = self[key] if isinstance(s, str): return s return ' '.join(s) def _get_list_value_for_modification(self, key): """ Return a list value for further modification. The list may be modified inplace and there is no need to do this afterwards:: self.table[var] = value """ try: value = self.table[key] except KeyError: try: value = self.parent[key] except AttributeError: value = [] if isinstance(value, list): value = value[:] else: value = [value] else: if not isinstance(value, list): value = [value] self.table[key] = value return value def append_value(self, var, val): """ Appends a value to the specified config key:: def build(bld): bld.env.append_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ current_value = self._get_list_value_for_modification(var) if isinstance(val, str): # if there were string everywhere we could optimize this val = [val] current_value.extend(val) def prepend_value(self, var, val): """ Prepends a value to the specified item:: def configure(conf): conf.env.prepend_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] self.table[var] = val + self._get_list_value_for_modification(var) def append_unique(self, var, val): """ Append a value to the specified item only if it's not already present:: def build(bld): bld.env.append_unique('CFLAGS', ['-O2', '-g']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] current_value = self._get_list_value_for_modification(var) for x in val: if x not in current_value: current_value.append(x) def get_merged_dict(self): """ Compute the merged dictionary from the fusion of self and all its parent :rtype: a ConfigSet object """ table_list = [] env = self while 1: table_list.insert(0, env.table) try: env = env.parent except AttributeError: break merged_table = {} for table in table_list: merged_table.update(table) return merged_table def store(self, filename): """ Write the :py:class:`ConfigSet` data into a file. See :py:meth:`ConfigSet.load` for reading such files. :param filename: file to use :type filename: string """ try: os.makedirs(os.path.split(filename)[0]) except OSError: pass buf = [] merged_table = self.get_merged_dict() keys = list(merged_table.keys()) keys.sort() for k in keys: if k != 'undo_stack': buf.append('%s = %r\n' % (k, merged_table[k])) Utils.writef(filename, ''.join(buf)) def load(self, filename): """ Retrieve the :py:class:`ConfigSet` data from a file. See :py:meth:`ConfigSet.store` for writing such files :param filename: file to use :type filename: string """ tbl = self.table code = Utils.readf(filename, m='rU') for m in re_imp.finditer(code): g = m.group tbl[g(2)] = eval(g(3)) Logs.debug('env: %s' % str(self.table)) def update(self, d): """ Dictionary interface: replace values from another dict :param d: object to use the value from :type d: dict-like object """ for k, v in d.items(): self[k] = v def stash(self): """ Store the object state, to provide a kind of transaction support:: env = ConfigSet() env.stash() try: env.append_value('CFLAGS', '-O3') call_some_method(env) finally: env.revert() The history is kept in a stack, and is lost during the serialization by :py:meth:`ConfigSet.store` """ orig = self.table tbl = self.table = self.table.copy() for x in tbl.keys(): tbl[x] = copy.deepcopy(tbl[x]) self.undo_stack = self.undo_stack + [orig] def revert(self): """ Reverts the object to a previous state. See :py:meth:`ConfigSet.stash` """ self.table = self.undo_stack.pop(-1) debian/waf-1.7/waflib/Context.py0000664000000000000000000004062312145745420013523 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Classes and functions required for waf commands """ import os, imp, sys from waflib import Utils, Errors, Logs import waflib.Node # the following 3 constants are updated on each new release (do not touch) HEXVERSION=0x1070a00 """Constant updated on new releases""" WAFVERSION="1.7.10" """Constant updated on new releases""" WAFREVISION="661a034d911e4379c9dfac604d7dfb086a8c4212" """Constant updated on new releases""" ABI = 98 """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" DBFILE = '.wafpickle-%s-%d-%d' % (sys.platform, sys.hexversion, ABI) """Name of the pickle file for storing the build data""" APPNAME = 'APPNAME' """Default application name (used by ``waf dist``)""" VERSION = 'VERSION' """Default application version (used by ``waf dist``)""" TOP = 'top' """The variable name for the top-level directory in wscript files""" OUT = 'out' """The variable name for the output directory in wscript files""" WSCRIPT_FILE = 'wscript' """Name of the waf script files""" launch_dir = '' """Directory from which waf has been called""" run_dir = '' """Location of the wscript file to use as the entry point""" top_dir = '' """Location of the project directory (top), if the project was configured""" out_dir = '' """Location of the build directory (out), if the project was configured""" waf_dir = '' """Directory containing the waf modules""" local_repo = '' """Local repository containing additional Waf tools (plugins)""" remote_repo = 'http://waf.googlecode.com/git/' """ Remote directory containing downloadable waf tools. The missing tools can be downloaded by using:: $ waf configure --download """ remote_locs = ['waflib/extras', 'waflib/Tools'] """ Remote directories for use with :py:const:`waflib.Context.remote_repo` """ g_module = None """ Module representing the main wscript file (see :py:const:`waflib.Context.run_dir`) """ STDOUT = 1 STDERR = -1 BOTH = 0 classes = [] """ List of :py:class:`waflib.Context.Context` subclasses that can be used as waf commands. The classes are added automatically by a metaclass. """ def create_context(cmd_name, *k, **kw): """ Create a new :py:class:`waflib.Context.Context` instance corresponding to the given command. Used in particular by :py:func:`waflib.Scripting.run_command` :param cmd_name: command :type cmd_name: string :param k: arguments to give to the context class initializer :type k: list :param k: keyword arguments to give to the context class initializer :type k: dict """ global classes for x in classes: if x.cmd == cmd_name: return x(*k, **kw) ctx = Context(*k, **kw) ctx.fun = cmd_name return ctx class store_context(type): """ Metaclass for storing the command classes into the list :py:const:`waflib.Context.classes` Context classes must provide an attribute 'cmd' representing the command to execute """ def __init__(cls, name, bases, dict): super(store_context, cls).__init__(name, bases, dict) name = cls.__name__ if name == 'ctx' or name == 'Context': return try: cls.cmd except AttributeError: raise Errors.WafError('Missing command for the context class %r (cmd)' % name) if not getattr(cls, 'fun', None): cls.fun = cls.cmd global classes classes.insert(0, cls) ctx = store_context('ctx', (object,), {}) """Base class for the :py:class:`waflib.Context.Context` classes""" class Context(ctx): """ Default context for waf commands, and base class for new command contexts. Context objects are passed to top-level functions:: def foo(ctx): print(ctx.__class__.__name__) # waflib.Context.Context Subclasses must define the attribute 'cmd': :param cmd: command to execute as in ``waf cmd`` :type cmd: string :param fun: function name to execute when the command is called :type fun: string .. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext """ errors = Errors """ Shortcut to :py:mod:`waflib.Errors` provided for convenience """ tools = {} """ A cache for modules (wscript files) read by :py:meth:`Context.Context.load` """ def __init__(self, **kw): try: rd = kw['run_dir'] except KeyError: global run_dir rd = run_dir # binds the context to the nodes in use to avoid a context singleton class node_class(waflib.Node.Node): pass self.node_class = node_class self.node_class.__module__ = "waflib.Node" self.node_class.__name__ = "Nod3" self.node_class.ctx = self self.root = self.node_class('', None) self.cur_script = None self.path = self.root.find_dir(rd) self.stack_path = [] self.exec_dict = {'ctx':self, 'conf':self, 'bld':self, 'opt':self} self.logger = None def __hash__(self): """ Return a hash value for storing context objects in dicts or sets. The value is not persistent. :return: hash value :rtype: int """ return id(self) def load(self, tool_list, *k, **kw): """ Load a Waf tool as a module, and try calling the function named :py:const:`waflib.Context.Context.fun` from it. A ``tooldir`` value may be provided as a list of module paths. :type tool_list: list of string or space-separated string :param tool_list: list of Waf tools to use """ tools = Utils.to_list(tool_list) path = Utils.to_list(kw.get('tooldir', '')) for t in tools: module = load_tool(t, path) fun = getattr(module, kw.get('name', self.fun), None) if fun: fun(self) def execute(self): """ Execute the command. Redefine this method in subclasses. """ global g_module self.recurse([os.path.dirname(g_module.root_path)]) def pre_recurse(self, node): """ Method executed immediately before a folder is read by :py:meth:`waflib.Context.Context.recurse`. The node given is set as an attribute ``self.cur_script``, and as the current path ``self.path`` :param node: script :type node: :py:class:`waflib.Node.Node` """ self.stack_path.append(self.cur_script) self.cur_script = node self.path = node.parent def post_recurse(self, node): """ Restore ``self.cur_script`` and ``self.path`` right after :py:meth:`waflib.Context.Context.recurse` terminates. :param node: script :type node: :py:class:`waflib.Node.Node` """ self.cur_script = self.stack_path.pop() if self.cur_script: self.path = self.cur_script.parent def recurse(self, dirs, name=None, mandatory=True, once=True): """ Run user code from the supplied list of directories. The directories can be either absolute, or relative to the directory of the wscript file. The methods :py:meth:`waflib.Context.Context.pre_recurse` and :py:meth:`waflib.Context.Context.post_recurse` are called immediately before and after a script has been executed. :param dirs: List of directories to visit :type dirs: list of string or space-separated string :param name: Name of function to invoke from the wscript :type name: string :param mandatory: whether sub wscript files are required to exist :type mandatory: bool :param once: read the script file once for a particular context :type once: bool """ try: cache = self.recurse_cache except AttributeError: cache = self.recurse_cache = {} for d in Utils.to_list(dirs): if not os.path.isabs(d): # absolute paths only d = os.path.join(self.path.abspath(), d) WSCRIPT = os.path.join(d, WSCRIPT_FILE) WSCRIPT_FUN = WSCRIPT + '_' + (name or self.fun) node = self.root.find_node(WSCRIPT_FUN) if node and (not once or node not in cache): cache[node] = True self.pre_recurse(node) try: function_code = node.read('rU') exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) finally: self.post_recurse(node) elif not node: node = self.root.find_node(WSCRIPT) tup = (node, name or self.fun) if node and (not once or tup not in cache): cache[tup] = True self.pre_recurse(node) try: wscript_module = load_module(node.abspath()) user_function = getattr(wscript_module, (name or self.fun), None) if not user_function: if not mandatory: continue raise Errors.WafError('No function %s defined in %s' % (name or self.fun, node.abspath())) user_function(self) finally: self.post_recurse(node) elif not node: if not mandatory: continue raise Errors.WafError('No wscript file in directory %s' % d) def exec_command(self, cmd, **kw): """ Execute a command and return the exit status. If the context has the attribute 'log', capture and log the process stderr/stdout for logging purposes:: def run(tsk): ret = tsk.generator.bld.exec_command('touch foo.txt') return ret This method captures the standard/error outputs (Issue 1101), but it does not return the values unlike :py:meth:`waflib.Context.Context.cmd_and_log` :param cmd: command argument for subprocess.Popen :param kw: keyword arguments for subprocess.Popen """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) Logs.debug('runner: %r' % cmd) Logs.debug('runner_env: kw=%s' % kw) if self.logger: self.logger.info(cmd) if 'stdout' not in kw: kw['stdout'] = subprocess.PIPE if 'stderr' not in kw: kw['stderr'] = subprocess.PIPE try: if kw['stdout'] or kw['stderr']: p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() ret = p.returncode else: out, err = (None, None) ret = subprocess.Popen(cmd, **kw).wait() except Exception as e: raise Errors.WafError('Execution failure: %s' % str(e), ex=e) if out: if not isinstance(out, str): out = out.decode(sys.stdout.encoding or 'iso8859-1') if self.logger: self.logger.debug('out: %s' % out) else: sys.stdout.write(out) if err: if not isinstance(err, str): err = err.decode(sys.stdout.encoding or 'iso8859-1') if self.logger: self.logger.error('err: %s' % err) else: sys.stderr.write(err) return ret def cmd_and_log(self, cmd, **kw): """ Execute a command and return stdout if the execution is successful. An exception is thrown when the exit status is non-0. In that case, both stderr and stdout will be bound to the WafError object:: def configure(conf): out = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.STDOUT, quiet=waflib.Context.BOTH) (out, err) = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.BOTH) try: conf.cmd_and_log(['which', 'someapp'], output=waflib.Context.BOTH) except Exception as e: print(e.stdout, e.stderr) :param cmd: args for subprocess.Popen :param kw: keyword arguments for subprocess.Popen """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) Logs.debug('runner: %r' % cmd) if 'quiet' in kw: quiet = kw['quiet'] del kw['quiet'] else: quiet = None if 'output' in kw: to_ret = kw['output'] del kw['output'] else: to_ret = STDOUT kw['stdout'] = kw['stderr'] = subprocess.PIPE if quiet is None: self.to_log(cmd) try: p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() except Exception as e: raise Errors.WafError('Execution failure: %s' % str(e), ex=e) if not isinstance(out, str): out = out.decode(sys.stdout.encoding or 'iso8859-1') if not isinstance(err, str): err = err.decode(sys.stdout.encoding or 'iso8859-1') if out and quiet != STDOUT and quiet != BOTH: self.to_log('out: %s' % out) if err and quiet != STDERR and quiet != BOTH: self.to_log('err: %s' % err) if p.returncode: e = Errors.WafError('Command %r returned %r' % (cmd, p.returncode)) e.returncode = p.returncode e.stderr = err e.stdout = out raise e if to_ret == BOTH: return (out, err) elif to_ret == STDERR: return err return out def fatal(self, msg, ex=None): """ Raise a configuration error to interrupt the execution immediately:: def configure(conf): conf.fatal('a requirement is missing') :param msg: message to display :type msg: string :param ex: optional exception object :type ex: exception """ if self.logger: self.logger.info('from %s: %s' % (self.path.abspath(), msg)) try: msg = '%s\n(complete log in %s)' % (msg, self.logger.handlers[0].baseFilename) except Exception: pass raise self.errors.ConfigurationError(msg, ex=ex) def to_log(self, msg): """ Log some information to the logger (if present), or to stderr. If the message is empty, it is not printed:: def build(bld): bld.to_log('starting the build') When in doubt, override this method, or provide a logger on the context class. :param msg: message :type msg: string """ if not msg: return if self.logger: self.logger.info(msg) else: sys.stderr.write(str(msg)) sys.stderr.flush() def msg(self, msg, result, color=None): """ Print a configuration message of the form ``msg: result``. The second part of the message will be in colors. The output can be disabled easly by setting ``in_msg`` to a positive value:: def configure(conf): self.in_msg = 1 conf.msg('Checking for library foo', 'ok') # no output :param msg: message to display to the user :type msg: string :param result: result to display :type result: string or boolean :param color: color to use, see :py:const:`waflib.Logs.colors_lst` :type color: string """ self.start_msg(msg) if not isinstance(color, str): color = result and 'GREEN' or 'YELLOW' self.end_msg(result, color) def start_msg(self, msg): """ Print the beginning of a 'Checking for xxx' message. See :py:meth:`waflib.Context.Context.msg` """ try: if self.in_msg: self.in_msg += 1 return except AttributeError: self.in_msg = 0 self.in_msg += 1 try: self.line_just = max(self.line_just, len(msg)) except AttributeError: self.line_just = max(40, len(msg)) for x in (self.line_just * '-', msg): self.to_log(x) Logs.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') def end_msg(self, result, color=None): """Print the end of a 'Checking for' message. See :py:meth:`waflib.Context.Context.msg`""" self.in_msg -= 1 if self.in_msg: return defcolor = 'GREEN' if result == True: msg = 'ok' elif result == False: msg = 'not found' defcolor = 'YELLOW' else: msg = str(result) self.to_log(msg) Logs.pprint(color or defcolor, msg) def load_special_tools(self, var, ban=[]): global waf_dir lst = self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) for x in lst: if not x.name in ban: load_tool(x.name.replace('.py', '')) cache_modules = {} """ Dictionary holding already loaded modules, keyed by their absolute path. The modules are added automatically by :py:func:`waflib.Context.load_module` """ def load_module(path): """ Load a source file as a python module. :param path: file path :type path: string :return: Loaded Python module :rtype: module """ try: return cache_modules[path] except KeyError: pass module = imp.new_module(WSCRIPT_FILE) try: code = Utils.readf(path, m='rU') except (IOError, OSError): raise Errors.WafError('Could not read the file %r' % path) module_dir = os.path.dirname(path) sys.path.insert(0, module_dir) exec(compile(code, path, 'exec'), module.__dict__) sys.path.remove(module_dir) cache_modules[path] = module return module def load_tool(tool, tooldir=None): """ Import a Waf tool (python module), and store it in the dict :py:const:`waflib.Context.Context.tools` :type tool: string :param tool: Name of the tool :type tooldir: list :param tooldir: List of directories to search for the tool module """ if tool == 'java': tool = 'javaw' # jython elif tool == 'compiler_cc': tool = 'compiler_c' # TODO remove in waf 1.8 else: tool = tool.replace('++', 'xx') if tooldir: assert isinstance(tooldir, list) sys.path = tooldir + sys.path try: __import__(tool) ret = sys.modules[tool] Context.tools[tool] = ret return ret finally: for d in tooldir: sys.path.remove(d) else: global waf_dir try: os.stat(os.path.join(waf_dir, 'waflib', 'extras', tool + '.py')) except OSError: try: os.stat(os.path.join(waf_dir, 'waflib', 'Tools', tool + '.py')) except OSError: d = tool # user has messed with sys.path else: d = 'waflib.Tools.%s' % tool else: d = 'waflib.extras.%s' % tool __import__(d) ret = sys.modules[d] Context.tools[tool] = ret return ret debian/waf-1.7/waflib/extras/0000775000000000000000000000000012145745420013026 5ustar debian/waf-1.7/waflib/extras/fc_open64.py0000664000000000000000000000277512145745420015176 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].insert(0, 'fc_open64') @conf def find_openf95(conf): """Find the Open64 Fortran Compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['openf95', 'openf90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_open64_version(fc) conf.env.FC_NAME = 'OPEN64' conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' @conf def openf95_flags(conf): v = conf.env v['FCFLAGS_DEBUG'] = ['-fullwarn'] @conf def openf95_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() openf95_modifier_func = getattr(conf, 'openf95_modifier_' + dest_os, None) if openf95_modifier_func: openf95_modifier_func() @conf def get_open64_version(conf, fc): """Get the Open64 compiler version""" version_re = re.compile(r"Open64 Compiler Suite: *Version *(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-version'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Open64 version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_openf95() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.openf95_flags() conf.openf95_modifier_platform() debian/waf-1.7/waflib/extras/msvs.py0000664000000000000000000007257012145745420014403 0ustar #! /usr/bin/env python # encoding: utf-8 # Avalanche Studios 2009-2011 # Thomas Nagy 2011 """ 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. """ """ To add this tool to your project: def options(conf): opt.load('msvs') It can be a good idea to add the sync_exec tool too. To generate solution files: $ waf configure msvs To customize the outputs, provide subclasses in your wscript files: from waflib.extras import msvs class vsnode_target(msvs.vsnode_target): def get_build_command(self, props): # likely to be required return "waf.bat build" def collect_source(self): # likely to be required ... class msvs_bar(msvs.msvs_generator): def init(self): msvs.msvs_generator.init(self) self.vsnode_target = vsnode_target The msvs class re-uses the same build() function for reading the targets (task generators), you may therefore specify msvs settings on the context object: def build(bld): bld.solution_name = 'foo.sln' bld.waf_command = 'waf.bat' bld.projects_dir = bld.srcnode.make_node('.depproj') bld.projects_dir.mkdir() For visual studio 2008, the command is called 'msvs2008', and the classes such as vsnode_target are wrapped by a decorator class 'wrap_2008' to provide special functionality. ASSUMPTIONS: * a project can be either a directory or a target, vcxproj files are written only for targets that have source files * each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path """ import os, re, sys import uuid # requires python 2.5 from waflib.Build import BuildContext from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' PROJECT_TEMPLATE = r''' ${for b in project.build_properties} ${b.configuration} ${b.platform} ${endfor} {${project.uuid}} MakeFileProj ${project.name} ${for b in project.build_properties} Makefile ${b.outdir} ${endfor} ${for b in project.build_properties} ${endfor} ${for b in project.build_properties} ${xml:project.get_build_command(b)} ${xml:project.get_rebuild_command(b)} ${xml:project.get_clean_command(b)} ${xml:b.includes_search_path} ${xml:b.preprocessor_definitions};$(NMakePreprocessorDefinitions) ${xml:b.includes_search_path} $(ExecutablePath) ${if getattr(b, 'output_file', None)} ${xml:b.output_file} ${endif} ${if getattr(b, 'deploy_dir', None)} ${xml:b.deploy_dir} ${endif} ${endfor} ${for b in project.build_properties} ${if getattr(b, 'deploy_dir', None)} CopyToHardDrive ${endif} ${endfor} ${for x in project.source} <${project.get_key(x)} Include='${x.abspath()}' /> ${endfor} ''' FILTER_TEMPLATE = ''' ${for x in project.source} <${project.get_key(x)} Include="${x.abspath()}"> ${project.get_filter_name(x.parent)} ${endfor} ${for x in project.dirs()} {${project.make_uuid(x.abspath())}} ${endfor} ''' PROJECT_2008_TEMPLATE = r''' ${if project.build_properties} ${for b in project.build_properties} ${endfor} ${else} ${endif} ${if project.build_properties} ${for b in project.build_properties} ${endfor} ${else} ${endif} ${project.display_filter()} ''' SOLUTION_TEMPLATE = '''Microsoft Visual Studio Solution File, Format Version ${project.numver} # Visual Studio ${project.vsver} ${for p in project.all_projects} Project("{${p.ptype()}}") = "${p.name}", "${p.title}", "{${p.uuid}}" EndProject${endfor} Global GlobalSection(SolutionConfigurationPlatforms) = preSolution ${if project.all_projects} ${for (configuration, platform) in project.all_projects[0].ctx.project_configurations()} ${configuration}|${platform} = ${configuration}|${platform} ${endfor} ${endif} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution ${for p in project.all_projects} ${if hasattr(p, 'source')} ${for b in p.build_properties} {${p.uuid}}.${b.configuration}|${b.platform}.ActiveCfg = ${b.configuration}|${b.platform} ${if getattr(p, 'is_active', None)} {${p.uuid}}.${b.configuration}|${b.platform}.Build.0 = ${b.configuration}|${b.platform} ${endif} ${endfor} ${endif} ${endfor} EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution ${for p in project.all_projects} ${if p.parent} {${p.uuid}} = {${p.parent.uuid}} ${endif} ${endfor} EndGlobalSection EndGlobal ''' COMPILE_TEMPLATE = '''def f(project): lst = [] def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") %s #f = open('cmd.txt', 'w') #f.write(str(lst)) #f.close() return ''.join(lst) ''' reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) def compile_template(line): """ Compile a template expression into a python function (like jsps, but way shorter) """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return "\\" elif g('subst'): extr.append(g('code')) return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) indent = 0 buf = [] app = buf.append def app(txt): buf.append(indent * '\t' + txt) for x in range(len(extr)): if params[x]: app("lst.append(%r)" % params[x]) f = extr[x] if f.startswith('if') or f.startswith('for'): app(f + ':') indent += 1 elif f.startswith('py:'): app(f[3:]) elif f.startswith('endif') or f.startswith('endfor'): indent -= 1 elif f.startswith('else') or f.startswith('elif'): indent -= 1 app(f + ':') indent += 1 elif f.startswith('xml:'): app('lst.append(xml_escape(%s))' % f[4:]) else: #app('lst.append((%s) or "cannot find %s")' % (f, f)) app('lst.append(%s)' % f) if extr: if params[-1]: app("lst.append(%r)" % params[-1]) fun = COMPILE_TEMPLATE % "\n\t".join(buf) #print(fun) return Task.funex(fun) re_blank = re.compile('(\n|\r|\\s)*\n', re.M) def rm_blank_lines(txt): txt = re_blank.sub('\r\n', txt) return txt BOM = '\xef\xbb\xbf' try: BOM = bytes(BOM, 'iso8859-1') # python 3 except: pass def stealth_write(self, data, flags='wb'): try: x = unicode except: data = data.encode('utf-8') # python 3 else: data = data.decode(sys.getfilesystemencoding(), 'replace') data = data.encode('utf-8') if self.name.endswith('.vcproj') or self.name.endswith('.vcxproj'): data = BOM + data try: txt = self.read(flags='rb') if txt != data: raise ValueError('must write') except (IOError, ValueError): self.write(data, flags=flags) else: Logs.debug('msvs: skipping %s' % self.abspath()) Node.Node.stealth_write = stealth_write re_quote = re.compile("[^a-zA-Z0-9-]") def quote(s): return re_quote.sub("_", s) def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") def make_uuid(v, prefix = None): """ simple utility function """ if isinstance(v, dict): keys = list(v.keys()) keys.sort() tmp = str([(k, v[k]) for k in keys]) else: tmp = str(v) d = Utils.md5(tmp.encode()).hexdigest().upper() if prefix: d = '%s%s' % (prefix, d[8:]) gid = uuid.UUID(d, version = 4) return str(gid).upper() def diff(node, fromnode): # difference between two nodes, but with "(..)" instead of ".." c1 = node c2 = fromnode c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while id(c1) != id(c2): lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent for i in range(up): lst.append('(..)') lst.reverse() return tuple(lst) class build_property(object): pass class vsnode(object): """ Abstract class representing visual studio elements We assume that all visual studio nodes have a uuid and a parent """ def __init__(self, ctx): self.ctx = ctx # msvs context self.name = '' # string, mandatory self.vspath = '' # path in visual studio (name for dirs, absolute path for projects) self.uuid = '' # string, mandatory self.parent = None # parent node for visual studio nesting def get_waf(self): """ Override in subclasses... """ return 'cd /d "%s" & %s' % (self.ctx.srcnode.abspath(), getattr(self.ctx, 'waf_command', 'waf.bat')) def ptype(self): """ Return a special uuid for projects written in the solution file """ pass def write(self): """ Write the project file, by default, do nothing """ pass def make_uuid(self, val): """ Alias for creating uuid values easily (the templates cannot access global variables) """ return make_uuid(val) class vsnode_vsdir(vsnode): """ Nodes representing visual studio folders (which do not match the filesystem tree!) """ VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8" def __init__(self, ctx, uuid, name, vspath=''): vsnode.__init__(self, ctx) self.title = self.name = name self.uuid = uuid self.vspath = vspath or name def ptype(self): return self.VS_GUID_SOLUTIONFOLDER class vsnode_project(vsnode): """ Abstract class representing visual studio project elements A project is assumed to be writable, and has a node representing the file to write to """ VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" def ptype(self): return self.VS_GUID_VCPROJ def __init__(self, ctx, node): vsnode.__init__(self, ctx) self.path = node self.uuid = make_uuid(node.abspath()) self.name = node.name self.title = self.path.abspath() self.source = [] # list of node objects self.build_properties = [] # list of properties (nmake commands, output dir, etc) def dirs(self): """ Get the list of parent folders of the source files (header files included) for writing the filters """ lst = [] def add(x): if x.height() > self.tg.path.height() and x not in lst: lst.append(x) add(x.parent) for x in self.source: add(x.parent) return lst def write(self): Logs.debug('msvs: creating %r' % self.path) # first write the project file template1 = compile_template(PROJECT_TEMPLATE) proj_str = template1(self) proj_str = rm_blank_lines(proj_str) self.path.stealth_write(proj_str) # then write the filter template2 = compile_template(FILTER_TEMPLATE) filter_str = template2(self) filter_str = rm_blank_lines(filter_str) tmp = self.path.parent.make_node(self.path.name + '.filters') tmp.stealth_write(filter_str) def get_key(self, node): """ required for writing the source files """ name = node.name if name.endswith('.cpp') or name.endswith('.c'): return 'ClCompile' return 'ClInclude' def collect_properties(self): """ Returns a list of triplet (configuration, platform, output_directory) """ ret = [] for c in self.ctx.configurations: for p in self.ctx.platforms: x = build_property() x.outdir = '' x.configuration = c x.platform = p x.preprocessor_definitions = '' x.includes_search_path = '' # can specify "deploy_dir" too ret.append(x) self.build_properties = ret def get_build_params(self, props): opt = '--execsolution=%s' % self.ctx.get_solution_node().abspath() return (self.get_waf(), opt) def get_build_command(self, props): return "%s build %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build %s" % self.get_build_params(props) def get_filter_name(self, node): lst = diff(node, self.tg.path) return '\\'.join(lst) or '.' class vsnode_alias(vsnode_project): def __init__(self, ctx, node, name): vsnode_project.__init__(self, ctx, node) self.name = name self.output_file = '' class vsnode_build_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make all" (starting one process by target is slow) This is the only alias enabled by default """ def __init__(self, ctx, node, name='build_all_projects'): vsnode_alias.__init__(self, ctx, node, name) self.is_active = True class vsnode_install_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make install" """ def __init__(self, ctx, node, name='install_all_projects'): vsnode_alias.__init__(self, ctx, node, name) def get_build_command(self, props): return "%s build install %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build install %s" % self.get_build_params(props) class vsnode_project_view(vsnode_alias): """ Fake target used to emulate a file system view """ def __init__(self, ctx, node, name='project_view'): vsnode_alias.__init__(self, ctx, node, name) self.tg = self.ctx() # fake one, cannot remove self.exclude_files = Node.exclude_regs + ''' waf-1.7.* waf3-1.7.*/** .waf-1.7.* .waf3-1.7.*/** **/*.sdf **/*.suo **/*.ncb **/%s ''' % Options.lockfile def collect_source(self): # this is likely to be slow self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files) def get_build_command(self, props): params = self.get_build_params(props) + (self.ctx.cmd,) return "%s %s %s" % params def get_clean_command(self, props): return "" def get_rebuild_command(self, props): return self.get_build_command(props) class vsnode_target(vsnode_project): """ Visual studio project representing a targets (programs, libraries, etc) and bound to a task generator """ def __init__(self, ctx, tg): """ A project is more or less equivalent to a file/folder """ base = getattr(ctx, 'projects_dir', None) or tg.path node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node vsnode_project.__init__(self, ctx, node) self.name = quote(tg.name) self.tg = tg # task generator def get_build_params(self, props): """ Override the default to add the target name """ opt = '--execsolution=%s' % self.ctx.get_solution_node().abspath() if getattr(self, 'tg', None): opt += " --targets=%s" % self.tg.name return (self.get_waf(), opt) def collect_source(self): tg = self.tg source_files = tg.to_nodes(getattr(tg, 'source', [])) include_dirs = Utils.to_list(getattr(tg, 'msvs_includes', [])) include_files = [] for x in include_dirs: if isinstance(x, str): x = tg.path.find_node(x) if x: lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)] include_files.extend(lst) # remove duplicates self.source.extend(list(set(source_files + include_files))) self.source.sort(key=lambda x: x.abspath()) def collect_properties(self): """ Visual studio projects are associated with platforms and configurations (for building especially) """ super(vsnode_target, self).collect_properties() for x in self.build_properties: x.outdir = self.path.parent.abspath() x.preprocessor_definitions = '' x.includes_search_path = '' try: tsk = self.tg.link_task except AttributeError: pass else: x.output_file = tsk.outputs[0].abspath() x.preprocessor_definitions = ';'.join(tsk.env.DEFINES) x.includes_search_path = ';'.join(self.tg.env.INCPATHS) class msvs_generator(BuildContext): '''generates a visual studio 2010 solution''' cmd = 'msvs' fun = 'build' def init(self): """ Some data that needs to be present """ if not getattr(self, 'configurations', None): self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc if not getattr(self, 'platforms', None): self.platforms = ['Win32'] if not getattr(self, 'all_projects', None): self.all_projects = [] if not getattr(self, 'project_extension', None): self.project_extension = '.vcxproj' if not getattr(self, 'projects_dir', None): self.projects_dir = self.srcnode.make_node('.depproj') self.projects_dir.mkdir() # bind the classes to the object, so that subclass can provide custom generators if not getattr(self, 'vsnode_vsdir', None): self.vsnode_vsdir = vsnode_vsdir if not getattr(self, 'vsnode_target', None): self.vsnode_target = vsnode_target if not getattr(self, 'vsnode_build_all', None): self.vsnode_build_all = vsnode_build_all if not getattr(self, 'vsnode_install_all', None): self.vsnode_install_all = vsnode_install_all if not getattr(self, 'vsnode_project_view', None): self.vsnode_project_view = vsnode_project_view self.numver = '11.00' self.vsver = '2010' def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) # user initialization self.init() # two phases for creating the solution self.collect_projects() # add project objects into "self.all_projects" self.write_files() # write the corresponding project and solution files def collect_projects(self): """ Fill the list self.all_projects with project objects Fill the list of build targets """ self.collect_targets() self.add_aliases() self.collect_dirs() default_project = getattr(self, 'default_project', None) def sortfun(x): if x.name == default_project: return '' return getattr(x, 'path', None) and x.path.abspath() or x.name self.all_projects.sort(key=sortfun) def write_files(self): """ Write the project and solution files from the data collected so far. It is unlikely that you will want to change this """ for p in self.all_projects: p.write() # and finally write the solution file node = self.get_solution_node() node.parent.mkdir() Logs.warn('Creating %r' % node) template1 = compile_template(SOLUTION_TEMPLATE) sln_str = template1(self) sln_str = rm_blank_lines(sln_str) node.stealth_write(sln_str) def get_solution_node(self): """ The solution filename is required when writing the .vcproj files return self.solution_node and if it does not exist, make one """ try: return self.solution_node except: pass solution_name = getattr(self, 'solution_name', None) if not solution_name: solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.sln' if os.path.isabs(solution_name): self.solution_node = self.root.make_node(solution_name) else: self.solution_node = self.srcnode.make_node(solution_name) return self.solution_node def project_configurations(self): """ Helper that returns all the pairs (config,platform) """ ret = [] for c in self.configurations: for p in self.platforms: ret.append((c, p)) return ret def collect_targets(self): """ Process the list of task generators """ for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue if not hasattr(tg, 'msvs_includes'): tg.msvs_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', [])) tg.post() if not getattr(tg, 'link_task', None): continue p = self.vsnode_target(self, tg) p.collect_source() # delegate this processing p.collect_properties() self.all_projects.append(p) def add_aliases(self): """ Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7 We also add an alias for "make install" (disabled by default) """ base = getattr(self, 'projects_dir', None) or self.tg.path node_project = base.make_node('build_all_projects' + self.project_extension) # Node p_build = self.vsnode_build_all(self, node_project) p_build.collect_properties() self.all_projects.append(p_build) node_project = base.make_node('install_all_projects' + self.project_extension) # Node p_install = self.vsnode_install_all(self, node_project) p_install.collect_properties() self.all_projects.append(p_install) node_project = base.make_node('project_view' + self.project_extension) # Node p_view = self.vsnode_project_view(self, node_project) p_view.collect_source() p_view.collect_properties() self.all_projects.append(p_view) n = self.vsnode_vsdir(self, make_uuid(self.srcnode.abspath() + 'build_aliases'), "build_aliases") p_build.parent = p_install.parent = p_view.parent = n self.all_projects.append(n) def collect_dirs(self): """ Create the folder structure in the Visual studio project view """ seen = {} def make_parents(proj): # look at a project, try to make a parent if getattr(proj, 'parent', None): # aliases already have parents return x = proj.iter_path if x in seen: proj.parent = seen[x] return # There is not vsnode_vsdir for x. # So create a project representing the folder "x" n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.abspath()), x.name) n.iter_path = x.parent self.all_projects.append(n) # recurse up to the project directory if x.height() > self.srcnode.height() + 1: make_parents(n) for p in self.all_projects[:]: # iterate over a copy of all projects if not getattr(p, 'tg', None): # but only projects that have a task generator continue # make a folder for each task generator p.iter_path = p.tg.path make_parents(p) def wrap_2008(cls): class dec(cls): def __init__(self, *k, **kw): cls.__init__(self, *k, **kw) self.project_template = PROJECT_2008_TEMPLATE def display_filter(self): root = build_property() root.subfilters = [] root.sourcefiles = [] root.source = [] root.name = '' @Utils.run_once def add_path(lst): if not lst: return root child = build_property() child.subfilters = [] child.sourcefiles = [] child.source = [] child.name = lst[-1] par = add_path(lst[:-1]) par.subfilters.append(child) return child for x in self.source: # this crap is for enabling subclasses to override get_filter_name tmp = self.get_filter_name(x.parent) tmp = tmp != '.' and tuple(tmp.split('\\')) or () par = add_path(tmp) par.source.append(x) def display(n): buf = [] for x in n.source: buf.append('\n' % (xml_escape(x.abspath()), self.get_key(x))) for x in n.subfilters: buf.append('' % xml_escape(x.name)) buf.append(display(x)) buf.append('') return '\n'.join(buf) return display(root) def get_key(self, node): """ If you do not want to let visual studio use the default file extensions, override this method to return a value: 0: C/C++ Code, 1: C++ Class, 2: C++ Header File, 3: C++ Form, 4: C++ Control, 5: Text File, 6: DEF File, 7: IDL File, 8: Makefile, 9: RGS File, 10: RC File, 11: RES File, 12: XSD File, 13: XML File, 14: HTML File, 15: CSS File, 16: Bitmap, 17: Icon, 18: Resx File, 19: BSC File, 20: XSX File, 21: C++ Web Service, 22: ASAX File, 23: Asp Page, 24: Document, 25: Discovery File, 26: C# File, 27: eFileTypeClassDiagram, 28: MHTML Document, 29: Property Sheet, 30: Cursor, 31: Manifest, 32: eFileTypeRDLC """ return '' def write(self): Logs.debug('msvs: creating %r' % self.path) template1 = compile_template(self.project_template) proj_str = template1(self) proj_str = rm_blank_lines(proj_str) self.path.stealth_write(proj_str) return dec class msvs_2008_generator(msvs_generator): '''generates a visual studio 2008 solution''' cmd = 'msvs2008' fun = msvs_generator.fun def init(self): if not getattr(self, 'project_extension', None): self.project_extension = '_2008.vcproj' if not getattr(self, 'solution_name', None): self.solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '_2008.sln' if not getattr(self, 'vsnode_target', None): self.vsnode_target = wrap_2008(vsnode_target) if not getattr(self, 'vsnode_build_all', None): self.vsnode_build_all = wrap_2008(vsnode_build_all) if not getattr(self, 'vsnode_install_all', None): self.vsnode_install_all = wrap_2008(vsnode_install_all) if not getattr(self, 'vsnode_project_view', None): self.vsnode_project_view = wrap_2008(vsnode_project_view) msvs_generator.init(self) self.numver = '10.00' self.vsver = '2008' def options(ctx): """ If the msvs option is used, try to detect if the build is made from visual studio """ ctx.add_option('--execsolution', action='store', help='when building with visual studio, use a build state file') old = BuildContext.execute def override_build_state(ctx): def lock(rm, add): uns = ctx.options.execsolution.replace('.sln', rm) uns = ctx.root.make_node(uns) try: uns.delete() except: pass uns = ctx.options.execsolution.replace('.sln', add) uns = ctx.root.make_node(uns) try: uns.write('') except: pass if ctx.options.execsolution: ctx.launch_dir = Context.top_dir # force a build for the whole project (invalid cwd when called by visual studio) lock('.lastbuildstate', '.unsuccessfulbuild') old(ctx) lock('.unsuccessfulbuild', '.lastbuildstate') else: old(ctx) BuildContext.execute = override_build_state debian/waf-1.7/waflib/extras/parallel_debug.py0000664000000000000000000002233412145745420016346 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) """ Debugging helper for parallel compilation, outputs a file named pdebug.svg in the source directory:: def options(opt): opt.load('parallel_debug') def configure(conf): conf.load('parallel_debug') def build(bld): ... """ import os, time, sys try: from Queue import Queue except: from queue import Queue from waflib import Runner, Options, Utils, Task, Logs, Errors #import random #random.seed(100) def options(opt): opt.add_option('--dtitle', action='store', default='Parallel build representation for %r' % ' '.join(sys.argv), help='title for the svg diagram', dest='dtitle') opt.add_option('--dwidth', action='store', type='int', help='diagram width', default=800, dest='dwidth') opt.add_option('--dtime', action='store', type='float', help='recording interval in seconds', default=0.009, dest='dtime') opt.add_option('--dband', action='store', type='int', help='band width', default=22, dest='dband') opt.add_option('--dmaxtime', action='store', type='float', help='maximum time, for drawing fair comparisons', default=0, dest='dmaxtime') # red #ff4d4d # green #4da74d # lila #a751ff color2code = { 'GREEN' : '#4da74d', 'YELLOW' : '#fefe44', 'PINK' : '#a751ff', 'RED' : '#cc1d1d', 'BLUE' : '#6687bb', 'CYAN' : '#34e2e2', } mp = {} info = [] # list of (text,color) def map_to_color(name): if name in mp: return mp[name] try: cls = Task.classes[name] except KeyError: return color2code['RED'] if cls.color in mp: return mp[cls.color] if cls.color in color2code: return color2code[cls.color] return color2code['RED'] def process(self): m = self.master if m.stop: m.out.put(self) return self.master.set_running(1, id(Utils.threading.currentThread()), self) # remove the task signature immediately before it is executed # in case of failure the task will be executed again try: del self.generator.bld.task_sigs[self.uid()] except: pass try: self.generator.bld.returned_tasks.append(self) self.log_display(self.generator.bld) ret = self.run() except Exception: self.err_msg = Utils.ex_stack() self.hasrun = Task.EXCEPTION # TODO cleanup m.error_handler(self) m.out.put(self) return if ret: self.err_code = ret self.hasrun = Task.CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = Utils.ex_stack() self.hasrun = Task.EXCEPTION else: self.hasrun = Task.SUCCESS if self.hasrun != Task.SUCCESS: m.error_handler(self) self.master.set_running(-1, id(Utils.threading.currentThread()), self) m.out.put(self) Task.TaskBase.process_back = Task.TaskBase.process Task.TaskBase.process = process old_start = Runner.Parallel.start def do_start(self): try: Options.options.dband except AttributeError: self.bld.fatal('use def options(opt): opt.load("parallel_debug")!') self.taskinfo = Queue() old_start(self) if self.dirty: process_colors(self) Runner.Parallel.start = do_start def set_running(self, by, i, tsk): self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by) ) Runner.Parallel.set_running = set_running def name2class(name): return name.replace(' ', '_').replace('.', '_') def process_colors(producer): # first, cast the parameters tmp = [] try: while True: tup = producer.taskinfo.get(False) tmp.append(list(tup)) except: pass try: ini = float(tmp[0][2]) except: return if not info: seen = [] for x in tmp: name = x[3] if not name in seen: seen.append(name) else: continue info.append((name, map_to_color(name))) info.sort(key=lambda x: x[0]) thread_count = 0 acc = [] for x in tmp: thread_count += x[6] acc.append("%d %d %f %r %d %d %d" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count)) data_node = producer.bld.path.make_node('pdebug.dat') data_node.write('\n'.join(acc)) tmp = [lst[:2] + [float(lst[2]) - ini] + lst[3:] for lst in tmp] st = {} for l in tmp: if not l[0] in st: st[l[0]] = len(st.keys()) tmp = [ [st[lst[0]]] + lst[1:] for lst in tmp ] THREAD_AMOUNT = len(st.keys()) st = {} for l in tmp: if not l[1] in st: st[l[1]] = len(st.keys()) tmp = [ [lst[0]] + [st[lst[1]]] + lst[2:] for lst in tmp ] BAND = Options.options.dband seen = {} acc = [] for x in range(len(tmp)): line = tmp[x] id = line[1] if id in seen: continue seen[id] = True begin = line[2] thread_id = line[0] for y in range(x + 1, len(tmp)): line = tmp[y] if line[1] == id: end = line[2] #print id, thread_id, begin, end #acc.append( ( 10*thread_id, 10*(thread_id+1), 10*begin, 10*end ) ) acc.append( (BAND * begin, BAND*thread_id, BAND*end - BAND*begin, BAND, line[3]) ) break if Options.options.dmaxtime < 0.1: gwidth = 1 for x in tmp: m = BAND * x[2] if m > gwidth: gwidth = m else: gwidth = BAND * Options.options.dmaxtime ratio = float(Options.options.dwidth) / gwidth gwidth = Options.options.dwidth gheight = BAND * (THREAD_AMOUNT + len(info) + 1.5) out = [] out.append(""" \n """ % (0, 0, gwidth + 4, gheight + 4, 0, 0, gwidth + 4, gheight + 4)) # main title if Options.options.dtitle: out.append("""%s """ % (gwidth/2, gheight - 5, Options.options.dtitle)) # the rectangles groups = {} for (x, y, w, h, clsname) in acc: try: groups[clsname].append((x, y, w, h)) except: groups[clsname] = [(x, y, w, h)] for cls in groups: out.append("\n" % name2class(cls)) for (x, y, w, h) in groups[cls]: out.append("""\n""" % (2 + x*ratio, 2 + y, w*ratio, h, map_to_color(cls))) out.append("\n") # output the caption cnt = THREAD_AMOUNT for (text, color) in info: # caption box b = BAND/2 out.append("""\n""" % (name2class(text), 2 + BAND, 5 + (cnt + 0.5) * BAND, b, b, color)) # caption text out.append("""%s\n""" % (2 + 2 * BAND, 5 + (cnt + 0.5) * BAND + 10, text)) cnt += 1 out.append(""" """) out.append("\n") node = producer.bld.path.make_node('pdebug.svg') node.write("".join(out)) Logs.warn('Created the diagram %r' % node.abspath()) p = node.parent.abspath() producer.bld.exec_command(['convert', p + os.sep + 'pdebug.svg', p + os.sep + 'pdebug.png']) debian/waf-1.7/waflib/extras/fc_xlf.py0000664000000000000000000000315212145745420014642 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils,Errors from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['aix'].insert(0, 'fc_xlf') @conf def find_xlf(conf): """Find the xlf program (will look in the environment variable 'FC')""" fc = conf.find_program(['xlf2003_r', 'xlf2003', 'xlf95_r', 'xlf95', 'xlf90_r', 'xlf90', 'xlf_r', 'xlf'], var='FC') fc = conf.cmd_to_list(fc) conf.get_xlf_version(fc) conf.env.FC_NAME='XLF' @conf def xlf_flags(conf): v = conf.env v['FCDEFINES_ST'] = '-WF,-D%s' v['FCFLAGS_fcshlib'] = ['-qpic=small'] v['FCFLAGS_DEBUG'] = ['-qhalt=w'] v['LINKFLAGS_fcshlib'] = ['-Wl,-shared'] @conf def xlf_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() xlf_modifier_func = getattr(conf, 'xlf_modifier_' + dest_os, None) if xlf_modifier_func: xlf_modifier_func() @conf def get_xlf_version(conf, fc): """Get the compiler version""" cmd = fc + ['-qversion'] try: out, err = conf.cmd_and_log(cmd, output=0) except Errors.WafError: conf.fatal('Could not find xlf %r' % cmd) for v in (r"IBM XL Fortran.* V(?P\d*)\.(?P\d*)",): version_re = re.compile(v, re.I).search match = version_re(out or err) if match: k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) break else: conf.fatal('Could not determine the XLF version.') def configure(conf): conf.find_xlf() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.xlf_flags() conf.xlf_modifier_platform() debian/waf-1.7/waflib/extras/why.py0000664000000000000000000000333312145745420014211 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ This tool modifies the task signature scheme to store and obtain information about the task execution (why it must run, etc):: def configure(conf): conf.load('why') After adding the tool, a full rebuild is necessary. """ from waflib import Task, Utils, Logs, Errors def signature(self): # compute the result one time, and suppose the scan_signature will give the good result try: return self.cache_sig except AttributeError: pass self.m = Utils.md5() self.m.update(self.hcode.encode()) id_sig = self.m.digest() # explicit deps self.sig_explicit_deps() exp_sig = self.m.digest() # env vars self.sig_vars() var_sig = self.m.digest() # implicit deps / scanner results if self.scan: try: self.sig_implicit_deps() except Errors.TaskRescan: return self.signature() ret = self.cache_sig = self.m.digest() + id_sig + exp_sig + var_sig return ret Task.Task.signature = signature old = Task.Task.runnable_status def runnable_status(self): ret = old(self) if ret == Task.RUN_ME: try: old_sigs = self.generator.bld.task_sigs[self.uid()] except: Logs.debug("task: task must run as no previous signature exists") else: new_sigs = self.cache_sig def v(x): return Utils.to_hex(x) Logs.debug("Task %r" % self) msgs = ['Task must run', '* Task code', '* Source file or manual dependency', '* Configuration data variable'] tmp = 'task: -> %s: %s %s' for x in range(len(msgs)): l = len(Utils.SIG_NIL) a = new_sigs[x*l : (x+1)*l] b = old_sigs[x*l : (x+1)*l] if (a != b): Logs.debug(tmp % (msgs[x].ljust(35), v(a), v(b))) if x > 0: break return ret Task.Task.runnable_status = runnable_status debian/waf-1.7/waflib/extras/pep8.py0000664000000000000000000000663612145745420014267 0ustar #! /usr/bin/env python # encoding: utf-8 # # written by Sylvain Rouquette, 2011 ''' Install pep8 module: $ easy_install pep8 or $ pip install pep8 To add the boost tool to the waf file: $ ./waf-light --tools=compat15,pep8 or, if you have waf >= 1.6.2 $ ./waf update --files=pep8 Then add this to your wscript: [at]extension('.py', 'wscript') def run_pep8(self, node): self.create_task('Pep8', node) ''' import threading from waflib import TaskGen, Task, Options pep8 = __import__('pep8') class Pep8(Task.Task): color = 'PINK' lock = threading.Lock() def check_options(self): if pep8.options: return pep8.options = Options.options pep8.options.prog = 'pep8' excl = pep8.options.exclude.split(',') pep8.options.exclude = [s.rstrip('/') for s in excl] if pep8.options.filename: pep8.options.filename = pep8.options.filename.split(',') if pep8.options.select: pep8.options.select = pep8.options.select.split(',') else: pep8.options.select = [] if pep8.options.ignore: pep8.options.ignore = pep8.options.ignore.split(',') elif pep8.options.select: # Ignore all checks which are not explicitly selected pep8.options.ignore = [''] elif pep8.options.testsuite or pep8.options.doctest: # For doctest and testsuite, all checks are required pep8.options.ignore = [] else: # The default choice: ignore controversial checks pep8.options.ignore = pep8.DEFAULT_IGNORE.split(',') pep8.options.physical_checks = pep8.find_checks('physical_line') pep8.options.logical_checks = pep8.find_checks('logical_line') pep8.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0) pep8.options.messages = {} def run(self): with Pep8.lock: self.check_options() pep8.input_file(self.inputs[0].abspath()) return 0 if not pep8.get_count() else -1 def options(opt): opt.add_option('-q', '--quiet', default=0, action='count', help="report only file names, or nothing with -qq") opt.add_option('-r', '--repeat', action='store_true', help="show all occurrences of the same error") opt.add_option('--exclude', metavar='patterns', default=pep8.DEFAULT_EXCLUDE, help="exclude files or directories which match these " "comma separated patterns (default: %s)" % pep8.DEFAULT_EXCLUDE, dest='exclude') opt.add_option('--filename', metavar='patterns', default='*.py', help="when parsing directories, only check filenames " "matching these comma separated patterns (default: " "*.py)") opt.add_option('--select', metavar='errors', default='', help="select errors and warnings (e.g. E,W6)") opt.add_option('--ignore', metavar='errors', default='', help="skip errors and warnings (e.g. E4,W)") opt.add_option('--show-source', action='store_true', help="show source code for each error") opt.add_option('--show-pep8', action='store_true', help="show text of PEP 8 for each error") opt.add_option('--statistics', action='store_true', help="count errors and warnings") opt.add_option('--count', action='store_true', help="print total number of errors and warnings " "to standard error and set exit code to 1 if " "total is not null") opt.add_option('--benchmark', action='store_true', help="measure processing speed") opt.add_option('--testsuite', metavar='dir', help="run regression tests from dir") opt.add_option('--doctest', action='store_true', help="run doctest on myself") debian/waf-1.7/waflib/extras/fc_cray.py0000664000000000000000000000272312145745420015012 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_cray') @conf def find_crayftn(conf): """Find the Cray fortran compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['crayftn'], var='FC') fc = conf.cmd_to_list(fc) conf.get_crayftn_version(fc) conf.env.FC_NAME = 'CRAY' conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' @conf def crayftn_flags(conf): v = conf.env v['_FCMODOUTFLAGS'] = ['-em', '-J.'] # enable module files and put them in the current directoy v['FCFLAGS_DEBUG'] = ['-m1'] # more verbose compiler warnings v['FCFLAGS_fcshlib'] = ['-h pic'] v['LINKFLAGS_fcshlib'] = ['-h shared'] v['FCSTLIB_MARKER'] = '-h static' v['FCSHLIB_MARKER'] = '-h dynamic' @conf def get_crayftn_version(conf, fc): version_re = re.compile(r"Cray Fortran\s*:\s*Version\s*(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-V'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Cray Fortran compiler version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_crayftn() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.crayftn_flags() debian/waf-1.7/waflib/extras/add_objects.py0000664000000000000000000000030012145745420015632 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) from waflib import Logs Logs.warn('This tool has been merged to the main library, remove the references to "add_objects"') debian/waf-1.7/waflib/extras/local_rpath.py0000664000000000000000000000103212145745420015664 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) from waflib.TaskGen import after_method, feature @after_method('propagate_uselib_vars') @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') def add_rpath_stuff(self): all = self.to_list(getattr(self, 'use', [])) while all: name = all.pop() try: tg = self.bld.get_tgen_by_name(name) except: continue self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) all.extend(self.to_list(getattr(tg, 'use', []))) debian/waf-1.7/waflib/extras/make.py0000664000000000000000000000631712145745420014324 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ A make-like way of executing the build, following the relationships between inputs/outputs This algorithm will lead to slower builds, will not be as flexible as "waf build", but it might be useful for building data files (?) It is likely to break in the following cases: - files are created dynamically (no inputs or outputs) - headers - building two files from different groups """ import re from waflib import Options, Task, Logs from waflib.Build import BuildContext class MakeContext(BuildContext): '''executes tasks in a step-by-step manner, following dependencies between inputs/outputs''' cmd = 'make' fun = 'build' def __init__(self, **kw): super(MakeContext, self).__init__(**kw) self.files = Options.options.files def get_build_iterator(self): if not self.files: while 1: yield super(MakeContext, self).get_build_iterator() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() provides = {} uses = {} all_tasks = [] tasks = [] for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.TaskBase): lst = [tg] else: lst = tg.tasks for tsk in lst: all_tasks.append(tsk) do_exec = False for node in getattr(tsk, 'inputs', []): try: uses[node].append(tsk) except: uses[node] = [tsk] if matcher(node, output=False): do_exec = True break for node in getattr(tsk, 'outputs', []): try: provides[node].append(tsk) except: provides[node] = [tsk] if matcher(node, output=True): do_exec = True break if do_exec: tasks.append(tsk) # so we have the tasks that we need to process, the list of all tasks, # the map of the tasks providing nodes, and the map of tasks using nodes if not tasks: # if there are no tasks matching, return everything in the current group result = all_tasks else: # this is like a big filter... result = set([]) seen = set([]) cur = set(tasks) while cur: result |= cur tosee = set([]) for tsk in cur: for node in getattr(tsk, 'inputs', []): if node in seen: continue seen.add(node) tosee |= set(provides.get(node, [])) cur = tosee result = list(result) Task.set_file_constraints(result) Task.set_precedence_constraints(result) yield result while 1: yield [] def get_matcher(self, pat): # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output == True and not out: return False if output == False and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match debian/waf-1.7/waflib/extras/bjam.py0000664000000000000000000000757012145745420014322 0ustar #! /usr/bin/env python # per rosengren 2011 from os import sep, readlink from os.path import abspath from waflib import Logs from waflib.TaskGen import feature, after_method from waflib.Task import Task, always_run def options(opt): grp = opt.add_option_group('Bjam Options') grp.add_option('--bjam_src', default=None, help='You can find it in /tools/jam/src') grp.add_option('--bjam_uname', default='linuxx86_64', help='bjam is built in /bin./bjam') grp.add_option('--bjam_config', default=None) grp.add_option('--bjam_toolset', default=None) def configure(cnf): if not cnf.env.BJAM_SRC: cnf.env.BJAM_SRC = cnf.options.bjam_src if not cnf.env.BJAM_UNAME: cnf.env.BJAM_UNAME = cnf.options.bjam_uname try: cnf.find_program('bjam', path_list=[ cnf.env.BJAM_SRC + sep + 'bin.' + cnf.env.BJAM_UNAME ]) except Exception as e: cnf.env.BJAM = None if not cnf.env.BJAM_CONFIG: cnf.env.BJAM_CONFIG = cnf.options.bjam_config if not cnf.env.BJAM_TOOLSET: cnf.env.BJAM_TOOLSET = cnf.options.bjam_toolset @feature('bjam') @after_method('process_rule') def process_bjam(self): if not self.bld.env.BJAM: self.create_task('bjam_creator') self.create_task('bjam_build') self.create_task('bjam_installer') if getattr(self, 'always', False): always_run(bjam_creator) always_run(bjam_build) always_run(bjam_installer) class bjam_creator(Task): ext_out = 'bjam_exe' vars=['BJAM_SRC', 'BJAM_UNAME'] def run(self): env = self.env gen = self.generator path = gen.path bld = gen.bld bjam = gen.bld.root.find_dir(env.BJAM_SRC) if not bjam: Logs.error('Can not find bjam source') return -1 bjam_exe_relpath = 'bin.' + env.BJAM_UNAME + '/bjam' bjam_exe = bjam.find_resource(bjam_exe_relpath) if bjam_exe: env.BJAM = bjam_exe.srcpath() return 0 bjam_cmd = ['./build.sh'] Logs.debug('runner: ' + bjam.srcpath() + '> ' + str(bjam_cmd)) result = self.exec_command(bjam_cmd, cwd=bjam.srcpath()) if not result == 0: Logs.error('bjam failed') return -1 bjam_exe = bjam.find_resource(bjam_exe_relpath) if bjam_exe: env.BJAM = bjam_exe.srcpath() return 0 Logs.error('bjam failed') return -1 class bjam_build(Task): ext_in = 'bjam_exe' ext_out = 'install' vars = ['BJAM_TOOLSET'] def run(self): env = self.env gen = self.generator path = gen.path bld = gen.bld if hasattr(gen, 'root'): build_root = path.find_node(gen.root) else: build_root = path jam = bld.srcnode.find_resource(env.BJAM_CONFIG) if jam: Logs.debug('bjam: Using jam configuration from ' + jam.srcpath()) jam_rel = jam.relpath_gen(build_root) else: Logs.warn('No build configuration in build_config/user-config.jam. Using default') jam_rel = None bjam_exe = bld.srcnode.find_node(env.BJAM) if not bjam_exe: Logs.error('env.BJAM is not set') return -1 bjam_exe_rel = bjam_exe.relpath_gen(build_root) cmd = ([bjam_exe_rel] + (['--user-config=' + jam_rel] if jam_rel else []) + ['--stagedir=' + path.get_bld().path_from(build_root)] + ['--debug-configuration'] + ['--with-' + lib for lib in self.generator.target] + (['toolset=' + env.BJAM_TOOLSET] if env.BJAM_TOOLSET else []) + ['link=' + 'shared'] + ['variant=' + 'release'] ) Logs.debug('runner: ' + build_root.srcpath() + '> ' + str(cmd)) ret = self.exec_command(cmd, cwd=build_root.srcpath()) if ret != 0: return ret self.set_outputs(path.get_bld().ant_glob('lib/*') + path.get_bld().ant_glob('bin/*')) return 0 class bjam_installer(Task): ext_in = 'install' def run(self): gen = self.generator path = gen.path for idir, pat in [('${LIBDIR}', 'lib/*'), ('${BINDIR}', 'bin/*')]: files = [] for n in path.get_bld().ant_glob(pat): try: t = readlink(n.srcpath()) gen.bld.symlink_as(sep.join([idir, n.name]), t, postpone=False) except OSError: files.append(n) gen.bld.install_files(idir, files, postpone=False) return 0 debian/waf-1.7/waflib/extras/freeimage.py0000664000000000000000000000410512145745420015324 0ustar #!/usr/bin/env python # encoding: utf-8 # # written by Sylvain Rouquette, 2011 ''' To add the freeimage tool to the waf file: $ ./waf-light --tools=compat15,freeimage or, if you have waf >= 1.6.2 $ ./waf update --files=freeimage The wscript will look like: def options(opt): opt.load('compiler_cxx freeimage') def configure(conf): conf.load('compiler_cxx freeimage') # you can call check_freeimage with some parameters. # It's optional on Linux, it's 'mandatory' on Windows if # you didn't use --fi-path on the command-line # conf.check_freeimage(path='FreeImage/Dist', fip=True) def build(bld): bld(source='main.cpp', target='app', use='FREEIMAGE') ''' from waflib import Utils from waflib.Configure import conf def options(opt): opt.add_option('--fi-path', type='string', default='', dest='fi_path', help='''path to the FreeImage directory \ where the files are e.g. /FreeImage/Dist''') opt.add_option('--fip', action='store_true', default=False, dest='fip', help='link with FreeImagePlus') opt.add_option('--fi-static', action='store_true', default=False, dest='fi_static', help="link as shared libraries") @conf def check_freeimage(self, path=None, fip=False): self.start_msg('Checking FreeImage') if not self.env['CXX']: self.fatal('you must load compiler_cxx before loading freeimage') prefix = self.options.fi_static and 'ST' or '' platform = Utils.unversioned_sys_platform() if platform == 'win32': if not path: self.fatal('you must specify the path to FreeImage. \ use --fi-path=/FreeImage/Dist') else: self.env['INCLUDES_FREEIMAGE'] = path self.env['%sLIBPATH_FREEIMAGE' % prefix] = path libs = ['FreeImage'] if self.options.fip: libs.append('FreeImagePlus') if platform == 'win32': self.env['%sLIB_FREEIMAGE' % prefix] = libs else: self.env['%sLIB_FREEIMAGE' % prefix] = [i.lower() for i in libs] self.end_msg('ok') def configure(conf): platform = Utils.unversioned_sys_platform() if platform == 'win32' and not conf.options.fi_path: return conf.check_freeimage(conf.options.fi_path, conf.options.fip) debian/waf-1.7/waflib/extras/smart_continue.py0000664000000000000000000000370512145745420016437 0ustar #! /usr/bin/env python # Thomas Nagy, 2011 # Try to cancel the tasks that cannot run with the option -k when an error occurs: # 1 direct file dependencies # 2 tasks listed in the before/after/ext_in/ext_out attributes from waflib import Task, Runner Task.CANCELED = 4 def cancel_next(self, tsk): if not isinstance(tsk, Task.TaskBase): return if tsk.hasrun >= Task.SKIPPED: # normal execution, no need to do anything here return try: canceled_tasks, canceled_nodes = self.canceled_tasks, self.canceled_nodes except AttributeError: canceled_tasks = self.canceled_tasks = set([]) canceled_nodes = self.canceled_nodes = set([]) try: canceled_nodes.update(tsk.outputs) except AttributeError: pass try: canceled_tasks.add(tsk) except AttributeError: pass def get_out(self): tsk = self.out.get() if not self.stop: self.add_more_tasks(tsk) self.count -= 1 self.dirty = True self.cancel_next(tsk) # new code def error_handler(self, tsk): if not self.bld.keep: self.stop = True self.error.append(tsk) self.cancel_next(tsk) # new code Runner.Parallel.cancel_next = cancel_next Runner.Parallel.get_out = get_out Runner.Parallel.error_handler = error_handler def get_next_task(self): tsk = self.get_next_task_smart_continue() if not tsk: return tsk try: canceled_tasks, canceled_nodes = self.canceled_tasks, self.canceled_nodes except AttributeError: pass else: # look in the tasks that this one is waiting on # if one of them was canceled, cancel this one too for x in tsk.run_after: if x in canceled_tasks: tsk.hasrun = Task.CANCELED self.cancel_next(tsk) break else: # so far so good, now consider the nodes for x in getattr(tsk, 'inputs', []) + getattr(tsk, 'deps', []): if x in canceled_nodes: tsk.hasrun = Task.CANCELED self.cancel_next(tsk) break return tsk Runner.Parallel.get_next_task_smart_continue = Runner.Parallel.get_next_task Runner.Parallel.get_next_task = get_next_task debian/waf-1.7/waflib/extras/fc_solstudio.py0000664000000000000000000000320112145745420016071 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_solstudio') @conf def find_solstudio(conf): """Find the Solaris Studio compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['sunf95', 'f95', 'sunf90', 'f90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_solstudio_version(fc) conf.env.FC_NAME = 'SOL' @conf def solstudio_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-Kpic'] v['FCFLAGS_DEBUG'] = ['-w3'] v['LINKFLAGS_fcshlib'] = ['-G'] v['FCSTLIB_MARKER'] = '-Bstatic' v['FCSHLIB_MARKER'] = '-Bdynamic' v['SONAME_ST'] = '-h %s' @conf def solstudio_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() solstudio_modifier_func = getattr(conf, 'solstudio_modifier_' + dest_os, None) if solstudio_modifier_func: solstudio_modifier_func() @conf def get_solstudio_version(conf, fc): """Get the compiler version""" version_re = re.compile(r"Sun Fortran 95 *(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-V'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Sun Studio Fortran version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_solstudio() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.solstudio_flags() conf.solstudio_modifier_platform() debian/waf-1.7/waflib/extras/fc_bgxlf.py0000664000000000000000000000137312145745420015156 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].insert(0, 'fc_bgxlf') @conf def find_bgxlf(conf): fc = conf.find_program(['bgxlf2003_r','bgxlf2003'], var='FC') fc = conf.cmd_to_list(fc) conf.get_xlf_version(fc) conf.env.FC_NAME = 'BGXLF' @conf def bg_flags(self): self.env.SONAME_ST = '' self.env.FCSHLIB_MARKER = '' self.env.FCSTLIB_MARKER = '' self.env.FCFLAGS_fcshlib = ['-fPIC'] self.env.LINKFLAGS_fcshlib = ['-G', '-Wl,-bexpfull'] def configure(conf): conf.find_bgxlf() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.xlf_flags() conf.bg_flags() debian/waf-1.7/waflib/extras/qnxnto.py0000664000000000000000000000364412145745420014736 0ustar #!/usr/bin/env python # encoding: utf-8 # Jérôme Carretero 2011 (zougloub) # QNX neutrino compatibility functions import sys, os from waflib import Utils class Popen(object): """ Popen cannot work on QNX from a threaded program: Forking in threads is not implemented in neutrino. Python's os.popen / spawn / fork won't work when running in threads (they will if in the main program thread) In waf, this happens mostly in build. And the use cases can be replaced by os.system() calls. """ __slots__ = ["prog", "kw", "popen", "verbose"] verbose = 0 def __init__(self, prog, **kw): try: self.prog = prog self.kw = kw self.popen = None if Popen.verbose: sys.stdout.write("Popen created: %r, kw=%r..." % (prog, kw)) do_delegate = kw.get('stdout', None) == -1 and kw.get('stderr', None) == -1 if do_delegate: if Popen.verbose: print("Delegating to real Popen") self.popen = self.real_Popen(prog, **kw) else: if Popen.verbose: print("Emulating") except Exception as e: if Popen.verbose: print("Exception: %s" % e) raise def __getattr__(self, name): if Popen.verbose: sys.stdout.write("Getattr: %s..." % name) if name in Popen.__slots__: if Popen.verbose: print("In slots!") return object.__getattr__(self, name) else: if self.popen is not None: if Popen.verbose: print("from Popen") return getattr(self.popen, name) else: if name == "wait": return self.emu_wait else: raise Exception("subprocess emulation: not implemented: %s" % name) def emu_wait(self): if Popen.verbose: print("emulated wait (%r kw=%r)" % (self.prog, self.kw)) if isinstance(self.prog, str): cmd = self.prog else: cmd = " ".join(self.prog) if 'cwd' in self.kw: cmd = 'cd "%s" && %s' % (self.kw['cwd'], cmd) return os.system(cmd) if sys.platform == "qnx6": Popen.real_Popen = Utils.subprocess.Popen Utils.subprocess.Popen = Popen debian/waf-1.7/waflib/extras/run_py_script.py0000664000000000000000000000750512145745420016307 0ustar #!/usr/bin/env python # encoding: utf-8 # Hans-Martin von Gaudecker, 2012 """ Run a Python script in the directory specified by **ctx.bldnode**. Select a Python version by specifying the **version** keyword for the task generator instance as integer 2 or 3. Default is 3. If the build environment has an attribute "PROJECT_PATHS" with a key "PROJECT_ROOT", its value will be appended to the PYTHONPATH. Same a string passed to the optional **add_to_pythonpath** keyword (appended after the PROJECT_ROOT). Usage:: ctx(features='run_py_script', version=3, source='some_script.py', target=['some_table.tex', 'some_figure.eps'], deps='some_data.csv', add_to_pythonpath='src/some/library') """ import os, re from waflib import Task, TaskGen, Logs def configure(conf): """TODO: Might need to be updated for Windows once "PEP 397":http://www.python.org/dev/peps/pep-0397/ is settled. """ conf.find_program('python', var='PY2CMD', mandatory=False) conf.find_program('python3', var='PY3CMD', mandatory=False) if not conf.env.PY2CMD and not conf.env.PY3CMD: conf.fatal("No Python interpreter found!") @Task.update_outputs class run_py_2_script(Task.Task): """Run a Python 2 script.""" run_str = '${PY2CMD} ${SRC[0].abspath()}' shell=True @Task.update_outputs class run_py_3_script(Task.Task): """Run a Python 3 script.""" run_str = '${PY3CMD} ${SRC[0].abspath()}' shell=True @TaskGen.feature('run_py_script') @TaskGen.before_method('process_source') def apply_run_py_script(tg): """Task generator for running either Python 2 or Python 3 on a single script. Attributes: * source -- A **single** source node or string. (required) * target -- A single target or list of targets (nodes or strings). * deps -- A single dependency or list of dependencies (nodes or strings) * add_to_pythonpath -- A string that will be appended to the PYTHONPATH environment variable. If the build environment has an attribute "PROJECT_PATHS" with a key "PROJECT_ROOT", its value will be appended to the PYTHONPATH. """ # Set the Python version to use, default to 3. v = getattr(tg, 'version', 3) if v not in (2, 3): raise ValueError("Specify the 'version' attribute for run_py_script task generator as integer 2 or 3.\n Got: %s" %v) # Convert sources and targets to nodes src_node = tg.path.find_resource(tg.source) tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] # Create the task. tsk = tg.create_task('run_py_%d_script' %v, src=src_node, tgt=tgt_nodes) # custom execution environment # TODO use a list and os.sep.join(lst) at the end instead of concatenating strings tsk.env.env = dict(os.environ) tsk.env.env['PYTHONPATH'] = tsk.env.env.get('PYTHONPATH', '') project_paths = getattr(tsk.env, 'PROJECT_PATHS', None) if project_paths and 'PROJECT_ROOT' in project_paths: tsk.env.env['PYTHONPATH'] += os.pathsep + project_paths['PROJECT_ROOT'].abspath() if getattr(tg, 'add_to_pythonpath', None): tsk.env.env['PYTHONPATH'] += os.pathsep + tg.add_to_pythonpath # Clean up the PYTHONPATH -- replace double occurrences of path separator tsk.env.env['PYTHONPATH'] = re.sub(os.pathsep + '+', os.pathsep, tsk.env.env['PYTHONPATH']) # Clean up the PYTHONPATH -- doesn't like starting with path separator if tsk.env.env['PYTHONPATH'].startswith(os.pathsep): tsk.env.env['PYTHONPATH'] = tsk.env.env['PYTHONPATH'][1:] # dependencies (if the attribute 'deps' changes, trigger a recompilation) for x in tg.to_list(getattr(tg, 'deps', [])): node = tg.path.find_resource(x) if not node: tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.nice_path())) tsk.dep_nodes.append(node) Logs.debug('deps: found dependencies %r for running %r' % (tsk.dep_nodes, src_node.nice_path())) # Bypass the execution of process_source by setting the source to an empty list tg.source = [] debian/waf-1.7/waflib/extras/fsc.py0000664000000000000000000000372312145745420014160 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Experimental F# stuff FSC="mono /path/to/fsc.exe" waf configure build """ from waflib import Utils, Task, Options, Logs, Errors from waflib.TaskGen import before_method, after_method, feature from waflib.Tools import ccroot, cs from waflib.Configure import conf ccroot.USELIB_VARS['fsc'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) @feature('fs') @before_method('process_source') def apply_fsc(self): cs_nodes = [] no_nodes = [] for x in self.to_nodes(self.source): if x.name.endswith('.fs'): cs_nodes.append(x) else: no_nodes.append(x) self.source = no_nodes bintype = getattr(self, 'type', self.gen.endswith('.dll') and 'library' or 'exe') self.cs_task = tsk = self.create_task('fsc', cs_nodes, self.path.find_or_declare(self.gen)) tsk.env.CSTYPE = '/target:%s' % bintype tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') if inst_to: # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) self.install_task = self.bld.install_files(inst_to, self.cs_task.outputs[:], env=self.env, chmod=mod) feature('fs')(cs.use_cs) after_method('apply_fsc')(cs.use_cs) feature('fs')(cs.debug_cs) after_method('apply_fsc', 'use_cs')(cs.debug_cs) class fsc(Task.Task): """ Compile F# files """ color = 'YELLOW' run_str = '${FSC} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' def configure(conf): """ Find a F# compiler, set the variable FSC for the compiler and FS_NAME (mono or fsc) """ conf.find_program(['fsc.exe', 'fsharpc'], var='FSC') conf.env.FSC = conf.cmd_to_list(conf.env.FSC) conf.env.ASS_ST = '/r:%s' conf.env.RES_ST = '/resource:%s' conf.env.FS_NAME = 'fsc' if str(conf.env.FSC).lower().find('fsharpc') > -1: conf.env.FS_NAME = 'mono' debian/waf-1.7/waflib/extras/win32_opts.py0000664000000000000000000001141412145745420015410 0ustar #! /usr/bin/env python # encoding: utf-8 """ Windows-specific optimizations This module can help reducing the overhead of listing files on windows (more than 10000 files). """ import os try: import cPickle except: import pickle as cPickle from waflib import Utils, Build, Context, Node, Logs try: TP = '%s\\*'.decode('ascii') except AttributeError: TP = '%s\\*' if Utils.is_win32: from waflib.extras import md5_tstamp import ctypes, ctypes.wintypes FindFirstFile = ctypes.windll.kernel32.FindFirstFileW FindNextFile = ctypes.windll.kernel32.FindNextFileW FindClose = ctypes.windll.kernel32.FindClose FILE_ATTRIBUTE_DIRECTORY = 0x10 INVALID_HANDLE_VALUE = -1 UPPER_FOLDERS = ('.', '..') try: UPPER_FOLDERS = [unicode(x) for x in UPPER_FOLDERS] except NameError: pass def cached_hash_file(self): try: cache = self.ctx.cache_listdir_cache_hash_file except AttributeError: cache = self.ctx.cache_listdir_cache_hash_file = {} if id(self.parent) in cache: try: t = cache[id(self.parent)][self.name] except KeyError: raise IOError('Not a file') else: # an opportunity to list the files and the timestamps at once findData = ctypes.wintypes.WIN32_FIND_DATAW() find = FindFirstFile(TP % self.parent.abspath(), ctypes.byref(findData)) if find == INVALID_HANDLE_VALUE: cache[id(self.parent)] = {} raise IOError('Not a file') cache[id(self.parent)] = lst_files = {} try: while True: if findData.cFileName not in UPPER_FOLDERS: thatsadir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY if not thatsadir: ts = findData.ftLastWriteTime d = (ts.dwLowDateTime << 32) | ts.dwHighDateTime lst_files[str(findData.cFileName)] = d if not FindNextFile(find, ctypes.byref(findData)): break except Exception as e: cache[id(self.parent)] = {} raise IOError('Not a file') finally: FindClose(find) t = lst_files[self.name] fname = self.abspath() if fname in Build.hashes_md5_tstamp: if Build.hashes_md5_tstamp[fname][0] == t: return Build.hashes_md5_tstamp[fname][1] try: fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT) except OSError: raise IOError('Cannot read from %r' % fname) f = os.fdopen(fd, 'rb') m = Utils.md5() rb = 1 try: while rb: rb = f.read(200000) m.update(rb) finally: f.close() # ensure that the cache is overwritten Build.hashes_md5_tstamp[fname] = (t, m.digest()) return m.digest() Node.Node.cached_hash_file = cached_hash_file def get_bld_sig_win32(self): try: return self.ctx.hash_cache[id(self)] except KeyError: pass except AttributeError: self.ctx.hash_cache = {} if not self.is_bld(): if self.is_child_of(self.ctx.srcnode): self.sig = self.cached_hash_file() else: self.sig = Utils.h_file(self.abspath()) self.ctx.hash_cache[id(self)] = ret = self.sig return ret Node.Node.get_bld_sig = get_bld_sig_win32 def isfile_cached(self): # optimize for nt.stat calls, assuming there are many files for few folders try: cache = self.__class__.cache_isfile_cache except AttributeError: cache = self.__class__.cache_isfile_cache = {} try: c1 = cache[id(self.parent)] except KeyError: c1 = cache[id(self.parent)] = [] curpath = self.parent.abspath() findData = ctypes.wintypes.WIN32_FIND_DATAW() find = FindFirstFile(TP % curpath, ctypes.byref(findData)) if find == INVALID_HANDLE_VALUE: Logs.error("invalid win32 handle isfile_cached %r" % self.abspath()) return os.path.isfile(self.abspath()) try: while True: if findData.cFileName not in UPPER_FOLDERS: thatsadir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY if not thatsadir: c1.append(str(findData.cFileName)) if not FindNextFile(find, ctypes.byref(findData)): break except Exception as e: Logs.error('exception while listing a folder %r %r' % (self.abspath(), e)) return os.path.isfile(self.abspath()) finally: FindClose(find) return self.name in c1 Node.Node.isfile_cached = isfile_cached def find_or_declare_win32(self, lst): # assuming that "find_or_declare" is called before the build starts, remove the calls to os.path.isfile if isinstance(lst, str): lst = [x for x in Node.split_path(lst) if x and x != '.'] node = self.get_bld().search(lst) if node: if not node.isfile_cached(): node.sig = None try: node.parent.mkdir() except: pass return node self = self.get_src() node = self.find_node(lst) if node: if not node.isfile_cached(): node.sig = None try: node.parent.mkdir() except: pass return node node = self.get_bld().make_node(lst) node.parent.mkdir() return node Node.Node.find_or_declare = find_or_declare_win32 debian/waf-1.7/waflib/extras/netcache_client.py0000664000000000000000000001704012145745420016512 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ A client for the network cache (playground/netcache/). Launch the server with: ./netcache_server, then use it for the builds by adding the following: def options(opt): opt.load('netcache_client') The parameters should be present in the environment in the form: NETCACHE=host:port@mode waf configure build where: mode: PUSH, PULL, PUSH_PULL host: host where the server resides, for example 127.0.0.1 port: by default the server runs on port 51200 The cache can be enabled for the build only: def options(opt): opt.load('netcache_client', funs=[]) def build(bld): bld.setup_netcache('localhost', 51200, 'PUSH_PULL') """ import os, socket, time, atexit from waflib import Task, Logs, Utils, Build, Options, Runner from waflib.Configure import conf BUF = 8192 * 16 HEADER_SIZE = 128 MODES = ['PUSH', 'PULL', 'PUSH_PULL'] STALE_TIME = 30 # seconds GET = 'GET' PUT = 'PUT' LST = 'LST' BYE = 'BYE' all_sigs_in_cache = (0.0, []) active_connections = Runner.Queue(0) def get_connection(): # return a new connection... do not forget to release it! try: ret = active_connections.get(block=False) except Exception: ret = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ret.connect(Task.net_cache[:2]) return ret def release_connection(conn, msg=''): if conn: active_connections.put(conn) def close_connection(conn, msg=''): if conn: data = '%s,%s' % (BYE, msg) try: conn.send(data.ljust(HEADER_SIZE)) except: pass try: conn.close() except: pass def close_all(): while active_connections.qsize(): conn = active_connections.get() try: close_connection(conn) except: pass atexit.register(close_all) def read_header(conn): cnt = 0 buf = [] while cnt < HEADER_SIZE: data = conn.recv(HEADER_SIZE - cnt) if not data: #import traceback #traceback.print_stack() raise ValueError('connection ended when reading a header %r' % buf) buf.append(data) cnt += len(data) return ''.join(buf) def check_cache(conn, ssig): """ List the files on the server, this is an optimization because it assumes that concurrent builds are rare """ global all_sigs_in_cache if not STALE_TIME: return if time.time() - all_sigs_in_cache[0] > STALE_TIME: params = (LST,'') conn.send(','.join(params).ljust(HEADER_SIZE)) # read what is coming back ret = read_header(conn) size = int(ret.split(',')[0]) buf = [] cnt = 0 while cnt < size: data = conn.recv(min(BUF, size-cnt)) if not data: raise ValueError('connection ended %r %r' % (cnt, size)) buf.append(data) cnt += len(data) all_sigs_in_cache = (time.time(), ''.join(buf).split('\n')) Logs.debug('netcache: server cache has %r entries' % len(all_sigs_in_cache[1])) if not ssig in all_sigs_in_cache[1]: raise ValueError('no file %s in cache' % ssig) class MissingFile(Exception): pass def recv_file(conn, ssig, count, p): check_cache(conn, ssig) params = (GET, ssig, str(count)) conn.send(','.join(params).ljust(HEADER_SIZE)) data = read_header(conn) size = int(data.split(',')[0]) if size == -1: raise MissingFile('no file %s - %s in cache' % (ssig, count)) # get the file, writing immediately # TODO a tmp file would be better f = open(p, 'wb') cnt = 0 while cnt < size: data = conn.recv(min(BUF, size-cnt)) if not data: raise ValueError('connection ended %r %r' % (cnt, size)) f.write(data) cnt += len(data) f.close() def put_data(conn, ssig, cnt, p): #print "pushing %r %r %r" % (ssig, cnt, p) size = os.stat(p).st_size params = (PUT, ssig, str(cnt), str(size)) conn.send(','.join(params).ljust(HEADER_SIZE)) f = open(p, 'rb') cnt = 0 while cnt < size: r = f.read(min(BUF, size-cnt)) while r: k = conn.send(r) if not k: raise ValueError('connection ended') cnt += k r = r[k:] #def put_data(conn, ssig, cnt, p): # size = os.stat(p).st_size # params = (PUT, ssig, str(cnt), str(size)) # conn.send(','.join(params).ljust(HEADER_SIZE)) # conn.send(','*size) # params = (BYE, 'he') # conn.send(','.join(params).ljust(HEADER_SIZE)) def can_retrieve_cache(self): if not Task.net_cache: return False if not self.outputs: return False if Task.net_cache[-1] == 'PUSH': return self.cached = False cnt = 0 sig = self.signature() ssig = self.uid().encode('hex') + sig.encode('hex') conn = None err = False try: try: conn = get_connection() for node in self.outputs: p = node.abspath() recv_file(conn, ssig, cnt, p) cnt += 1 except MissingFile as e: Logs.debug('netcache: file is not in the cache %r' % e) err = True except Exception as e: Logs.debug('netcache: could not get the files %r' % e) err = True # broken connection? remove this one close_connection(conn) conn = None finally: release_connection(conn) if err: return False for node in self.outputs: node.sig = sig #if self.generator.bld.progress_bar < 1: # self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True @Utils.run_once def put_files_cache(self): if not Task.net_cache: return if not self.outputs: return if Task.net_cache[-1] == 'PULL': return if getattr(self, 'cached', None): return #print "called put_files_cache", id(self) bld = self.generator.bld sig = self.signature() ssig = self.uid().encode('hex') + sig.encode('hex') conn = None cnt = 0 try: for node in self.outputs: # We could re-create the signature of the task with the signature of the outputs # in practice, this means hashing the output files # this is unnecessary try: if not conn: conn = get_connection() put_data(conn, ssig, cnt, node.abspath()) except Exception as e: Logs.debug("netcache: could not push the files %r" % e) # broken connection? remove this one close_connection(conn) conn = None cnt += 1 finally: release_connection(conn) bld.task_sigs[self.uid()] = self.cache_sig def hash_env_vars(self, env, vars_lst): if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass v = str([env[a] for a in vars_lst]) v = v.replace(self.srcnode.abspath().__repr__()[:-1], '') m = Utils.md5() m.update(v.encode()) ret = m.digest() Logs.debug('envhash: %r %r', ret, v) cache[idx] = ret return ret def uid(self): try: return self.uid_ except AttributeError: m = Utils.md5() src = self.generator.bld.srcnode up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.path_from(src).encode()) self.uid_ = m.digest() return self.uid_ @conf def setup_netcache(ctx, host, port, mode): Logs.warn('Using the network cache %s, %s, %s' % (host, port, mode)) Task.net_cache = (host, port, mode) Task.Task.can_retrieve_cache = can_retrieve_cache Task.Task.put_files_cache = put_files_cache Task.Task.uid = uid Build.BuildContext.hash_env_vars = hash_env_vars ctx.cache_global = Options.cache_global = True def options(opt): if not 'NETCACHE' in os.environ: Logs.warn('the network cache is disabled, set NETCACHE=host:port@mode to enable') else: v = os.environ['NETCACHE'] if v in MODES: host = socket.gethostname() port = 51200 mode = v else: mode = 'PUSH_PULL' host, port = v.split(':') if port.find('@'): port, mode = port.split('@') port = int(port) if not mode in MODES: opt.fatal('Invalid mode %s not in %r' % (mode, MODES)) setup_netcache(opt, host, port, mode) debian/waf-1.7/waflib/extras/fluid.py0000664000000000000000000000152512145745420014506 0ustar #!/usr/bin/python # encoding: utf-8 # Grygoriy Fuchedzhy 2009 """ Compile fluid files (fltk graphic library). Use the 'fluid' feature in conjuction with the 'cxx' feature. """ from waflib import Task from waflib.TaskGen import extension class fluid(Task.Task): color = 'BLUE' ext_out = ['.h'] run_str = '${FLUID} -c -o ${TGT[0].abspath()} -h ${TGT[1].abspath()} ${SRC}' @extension('.fl') def fluid(self, node): """add the .fl to the source list; the cxx file generated will be compiled when possible""" cpp = node.change_ext('.cpp') hpp = node.change_ext('.hpp') self.create_task('fluid', node, [cpp, hpp]) if 'cxx' in self.features: self.source.append(cpp) def configure(conf): conf.find_program('fluid', var='FLUID') conf.check_cfg(path='fltk-config', package='', args='--cxxflags --ldflags', uselib_store='FLTK', mandatory=True) debian/waf-1.7/waflib/extras/codelite.py0000664000000000000000000010251212145745420015171 0ustar #! /usr/bin/env python # encoding: utf-8 # CodeLite Project # Christian Klein (chrikle@berlios.de) # Created: Jan 2012 # As templete for this file I used the msvs.py # I hope this template will work proper """ 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. """ """ To add this tool to your project: def options(conf): opt.load('codelite') It can be a good idea to add the sync_exec tool too. To generate solution files: $ waf configure codelite To customize the outputs, provide subclasses in your wscript files: from waflib.extras import codelite class vsnode_target(codelite.vsnode_target): def get_build_command(self, props): # likely to be required return "waf.bat build" def collect_source(self): # likely to be required ... class codelite_bar(codelite.codelite_generator): def init(self): codelite.codelite_generator.init(self) self.vsnode_target = vsnode_target The codelite class re-uses the same build() function for reading the targets (task generators), you may therefore specify codelite settings on the context object: def build(bld): bld.codelite_solution_name = 'foo.workspace' bld.waf_command = 'waf.bat' bld.projects_dir = bld.srcnode.make_node('') bld.projects_dir.mkdir() ASSUMPTIONS: * a project can be either a directory or a target, project files are written only for targets that have source files * each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path """ import os, re, sys import uuid # requires python 2.5 from waflib.Build import BuildContext from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' PROJECT_TEMPLATE = r''' ${for x in project.source} ${if (project.get_key(x)=="sourcefile")} ${endif} ${endfor} ${for x in project.source} ${if (project.get_key(x)=="headerfile")} ${endif} ${endfor} $b = project.build_properties[0]} ${xml:project.get_rebuild_command(project.build_properties[0])} ${xml:project.get_clean_command(project.build_properties[0])} ${xml:project.get_build_command(project.build_properties[0])} ${xml:project.get_install_command(project.build_properties[0])} ${xml:project.get_build_and_install_command(project.build_properties[0])} ${xml:project.get_build_all_command(project.build_properties[0])} ${xml:project.get_rebuild_all_command(project.build_properties[0])} ${xml:project.get_clean_all_command(project.build_properties[0])} ${xml:project.get_build_and_install_all_command(project.build_properties[0])} None ''' SOLUTION_TEMPLATE = ''' ${for p in project.all_projects} ${endfor} ${for p in project.all_projects} ${endfor} ''' COMPILE_TEMPLATE = '''def f(project): lst = [] def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") %s #f = open('cmd.txt', 'w') #f.write(str(lst)) #f.close() return ''.join(lst) ''' reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) def compile_template(line): """ Compile a template expression into a python function (like jsps, but way shorter) """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return "\\" elif g('subst'): extr.append(g('code')) return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) indent = 0 buf = [] app = buf.append def app(txt): buf.append(indent * '\t' + txt) for x in range(len(extr)): if params[x]: app("lst.append(%r)" % params[x]) f = extr[x] if f.startswith('if') or f.startswith('for'): app(f + ':') indent += 1 elif f.startswith('py:'): app(f[3:]) elif f.startswith('endif') or f.startswith('endfor'): indent -= 1 elif f.startswith('else') or f.startswith('elif'): indent -= 1 app(f + ':') indent += 1 elif f.startswith('xml:'): app('lst.append(xml_escape(%s))' % f[4:]) else: #app('lst.append((%s) or "cannot find %s")' % (f, f)) app('lst.append(%s)' % f) if extr: if params[-1]: app("lst.append(%r)" % params[-1]) fun = COMPILE_TEMPLATE % "\n\t".join(buf) #print(fun) return Task.funex(fun) re_blank = re.compile('(\n|\r|\\s)*\n', re.M) def rm_blank_lines(txt): txt = re_blank.sub('\r\n', txt) return txt BOM = '\xef\xbb\xbf' try: BOM = bytes(BOM, 'iso8859-1') # python 3 except: pass def stealth_write(self, data, flags='wb'): try: x = unicode except: data = data.encode('utf-8') # python 3 else: data = data.decode(sys.getfilesystemencoding(), 'replace') data = data.encode('utf-8') if self.name.endswith('.project') or self.name.endswith('.project'): data = BOM + data try: txt = self.read(flags='rb') if txt != data: raise ValueError('must write') except (IOError, ValueError): self.write(data, flags=flags) else: Logs.debug('codelite: skipping %s' % self.abspath()) Node.Node.stealth_write = stealth_write re_quote = re.compile("[^a-zA-Z0-9-]") def quote(s): return re_quote.sub("_", s) def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") def make_uuid(v, prefix = None): """ simple utility function """ if isinstance(v, dict): keys = list(v.keys()) keys.sort() tmp = str([(k, v[k]) for k in keys]) else: tmp = str(v) d = Utils.md5(tmp.encode()).hexdigest().upper() if prefix: d = '%s%s' % (prefix, d[8:]) gid = uuid.UUID(d, version = 4) return str(gid).upper() def diff(node, fromnode): # difference between two nodes, but with "(..)" instead of ".." c1 = node c2 = fromnode c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while id(c1) != id(c2): lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent for i in range(up): lst.append('(..)') lst.reverse() return tuple(lst) class build_property(object): pass class vsnode(object): """ Abstract class representing visual studio elements We assume that all visual studio nodes have a uuid and a parent """ def __init__(self, ctx): self.ctx = ctx # codelite context self.name = '' # string, mandatory self.vspath = '' # path in visual studio (name for dirs, absolute path for projects) self.uuid = '' # string, mandatory self.parent = None # parent node for visual studio nesting def get_waf(self): """ Override in subclasses... """ return '%s/%s' % (self.ctx.srcnode.abspath(), getattr(self.ctx, 'waf_command', 'waf')) def ptype(self): """ Return a special uuid for projects written in the solution file """ pass def write(self): """ Write the project file, by default, do nothing """ pass def make_uuid(self, val): """ Alias for creating uuid values easily (the templates cannot access global variables) """ return make_uuid(val) class vsnode_vsdir(vsnode): """ Nodes representing visual studio folders (which do not match the filesystem tree!) """ VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8" def __init__(self, ctx, uuid, name, vspath=''): vsnode.__init__(self, ctx) self.title = self.name = name self.uuid = uuid self.vspath = vspath or name def ptype(self): return self.VS_GUID_SOLUTIONFOLDER class vsnode_project(vsnode): """ Abstract class representing visual studio project elements A project is assumed to be writable, and has a node representing the file to write to """ VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" def ptype(self): return self.VS_GUID_VCPROJ def __init__(self, ctx, node): vsnode.__init__(self, ctx) self.path = node self.uuid = make_uuid(node.abspath()) self.name = node.name self.title = self.path.abspath() self.source = [] # list of node objects self.build_properties = [] # list of properties (nmake commands, output dir, etc) def dirs(self): """ Get the list of parent folders of the source files (header files included) for writing the filters """ lst = [] def add(x): if x.height() > self.tg.path.height() and x not in lst: lst.append(x) add(x.parent) for x in self.source: add(x.parent) return lst def write(self): Logs.debug('codelite: creating %r' % self.path) #print "self.name:",self.name # first write the project file template1 = compile_template(PROJECT_TEMPLATE) proj_str = template1(self) proj_str = rm_blank_lines(proj_str) self.path.stealth_write(proj_str) # then write the filter #template2 = compile_template(FILTER_TEMPLATE) #filter_str = template2(self) #filter_str = rm_blank_lines(filter_str) #tmp = self.path.parent.make_node(self.path.name + '.filters') #tmp.stealth_write(filter_str) def get_key(self, node): """ required for writing the source files """ name = node.name if name.endswith('.cpp') or name.endswith('.c'): return 'sourcefile' return 'headerfile' def collect_properties(self): """ Returns a list of triplet (configuration, platform, output_directory) """ ret = [] for c in self.ctx.configurations: for p in self.ctx.platforms: x = build_property() x.outdir = '' x.configuration = c x.platform = p x.preprocessor_definitions = '' x.includes_search_path = '' # can specify "deploy_dir" too ret.append(x) self.build_properties = ret def get_build_params(self, props): opt = '' return (self.get_waf(), opt) def get_build_command(self, props): return "%s build %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build %s" % self.get_build_params(props) def get_install_command(self, props): return "%s install %s" % self.get_build_params(props) def get_build_and_install_command(self, props): return "%s build install %s" % self.get_build_params(props) def get_build_and_install_all_command(self, props): return "%s build install" % self.get_build_params(props)[0] def get_clean_all_command(self, props): return "%s clean" % self.get_build_params(props)[0] def get_build_all_command(self, props): return "%s build" % self.get_build_params(props)[0] def get_rebuild_all_command(self, props): return "%s clean build" % self.get_build_params(props)[0] def get_filter_name(self, node): lst = diff(node, self.tg.path) return '\\'.join(lst) or '.' class vsnode_alias(vsnode_project): def __init__(self, ctx, node, name): vsnode_project.__init__(self, ctx, node) self.name = name self.output_file = '' class vsnode_build_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make all" (starting one process by target is slow) This is the only alias enabled by default """ def __init__(self, ctx, node, name='build_all_projects'): vsnode_alias.__init__(self, ctx, node, name) self.is_active = True class vsnode_install_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make install" """ def __init__(self, ctx, node, name='install_all_projects'): vsnode_alias.__init__(self, ctx, node, name) def get_build_command(self, props): return "%s build install %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build install %s" % self.get_build_params(props) class vsnode_project_view(vsnode_alias): """ Fake target used to emulate a file system view """ def __init__(self, ctx, node, name='project_view'): vsnode_alias.__init__(self, ctx, node, name) self.tg = self.ctx() # fake one, cannot remove self.exclude_files = Node.exclude_regs + ''' waf-1.7.* waf3-1.7.*/** .waf-1.7.* .waf3-1.7.*/** **/*.sdf **/*.suo **/*.ncb **/%s ''' % Options.lockfile def collect_source(self): # this is likely to be slow self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files) def get_build_command(self, props): params = self.get_build_params(props) + (self.ctx.cmd,) return "%s %s %s" % params def get_clean_command(self, props): return "" def get_rebuild_command(self, props): return self.get_build_command(props) class vsnode_target(vsnode_project): """ CodeLite project representing a targets (programs, libraries, etc) and bound to a task generator """ def __init__(self, ctx, tg): """ A project is more or less equivalent to a file/folder """ base = getattr(ctx, 'projects_dir', None) or tg.path node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node vsnode_project.__init__(self, ctx, node) self.name = quote(tg.name) self.tg = tg # task generator def get_build_params(self, props): """ Override the default to add the target name """ opt = '' if getattr(self, 'tg', None): opt += " --targets=%s" % self.tg.name return (self.get_waf(), opt) def collect_source(self): tg = self.tg source_files = tg.to_nodes(getattr(tg, 'source', [])) include_dirs = Utils.to_list(getattr(tg, 'codelite_includes', [])) include_files = [] for x in include_dirs: if isinstance(x, str): x = tg.path.find_node(x) if x: lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)] include_files.extend(lst) # remove duplicates self.source.extend(list(set(source_files + include_files))) self.source.sort(key=lambda x: x.abspath()) def collect_properties(self): """ CodeLite projects are associated with platforms and configurations (for building especially) """ super(vsnode_target, self).collect_properties() for x in self.build_properties: x.outdir = self.path.parent.abspath() x.preprocessor_definitions = '' x.includes_search_path = '' try: tsk = self.tg.link_task except AttributeError: pass else: x.output_file = tsk.outputs[0].abspath() x.preprocessor_definitions = ';'.join(tsk.env.DEFINES) x.includes_search_path = ';'.join(self.tg.env.INCPATHS) class codelite_generator(BuildContext): '''generates a CodeLite workspace''' cmd = 'codelite' fun = 'build' def init(self): """ Some data that needs to be present """ if not getattr(self, 'configurations', None): self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc if not getattr(self, 'platforms', None): self.platforms = ['Win32'] if not getattr(self, 'all_projects', None): self.all_projects = [] if not getattr(self, 'project_extension', None): self.project_extension = '.project' if not getattr(self, 'projects_dir', None): self.projects_dir = self.srcnode.make_node('') self.projects_dir.mkdir() # bind the classes to the object, so that subclass can provide custom generators if not getattr(self, 'vsnode_vsdir', None): self.vsnode_vsdir = vsnode_vsdir if not getattr(self, 'vsnode_target', None): self.vsnode_target = vsnode_target if not getattr(self, 'vsnode_build_all', None): self.vsnode_build_all = vsnode_build_all if not getattr(self, 'vsnode_install_all', None): self.vsnode_install_all = vsnode_install_all if not getattr(self, 'vsnode_project_view', None): self.vsnode_project_view = vsnode_project_view self.numver = '11.00' self.vsver = '2010' def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) # user initialization self.init() # two phases for creating the solution self.collect_projects() # add project objects into "self.all_projects" self.write_files() # write the corresponding project and solution files def collect_projects(self): """ Fill the list self.all_projects with project objects Fill the list of build targets """ self.collect_targets() #self.add_aliases() #self.collect_dirs() default_project = getattr(self, 'default_project', None) def sortfun(x): if x.name == default_project: return '' return getattr(x, 'path', None) and x.path.abspath() or x.name self.all_projects.sort(key=sortfun) def write_files(self): """ Write the project and solution files from the data collected so far. It is unlikely that you will want to change this """ for p in self.all_projects: p.write() # and finally write the solution file node = self.get_solution_node() node.parent.mkdir() Logs.warn('Creating %r' % node) #a = dir(self.root) #for b in a: # print b #print self.group_names #print "Hallo2: ",self.root.listdir() #print getattr(self, 'codelite_solution_name', None) template1 = compile_template(SOLUTION_TEMPLATE) sln_str = template1(self) sln_str = rm_blank_lines(sln_str) node.stealth_write(sln_str) def get_solution_node(self): """ The solution filename is required when writing the .vcproj files return self.solution_node and if it does not exist, make one """ try: return self.solution_node except: pass codelite_solution_name = getattr(self, 'codelite_solution_name', None) if not codelite_solution_name: codelite_solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.workspace' setattr(self, 'codelite_solution_name', codelite_solution_name) if os.path.isabs(codelite_solution_name): self.solution_node = self.root.make_node(codelite_solution_name) else: self.solution_node = self.srcnode.make_node(codelite_solution_name) return self.solution_node def project_configurations(self): """ Helper that returns all the pairs (config,platform) """ ret = [] for c in self.configurations: for p in self.platforms: ret.append((c, p)) return ret def collect_targets(self): """ Process the list of task generators """ for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue if not hasattr(tg, 'codelite_includes'): tg.codelite_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', [])) tg.post() if not getattr(tg, 'link_task', None): continue p = self.vsnode_target(self, tg) p.collect_source() # delegate this processing p.collect_properties() self.all_projects.append(p) def add_aliases(self): """ Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7 We also add an alias for "make install" (disabled by default) """ base = getattr(self, 'projects_dir', None) or self.tg.path node_project = base.make_node('build_all_projects' + self.project_extension) # Node p_build = self.vsnode_build_all(self, node_project) p_build.collect_properties() self.all_projects.append(p_build) node_project = base.make_node('install_all_projects' + self.project_extension) # Node p_install = self.vsnode_install_all(self, node_project) p_install.collect_properties() self.all_projects.append(p_install) node_project = base.make_node('project_view' + self.project_extension) # Node p_view = self.vsnode_project_view(self, node_project) p_view.collect_source() p_view.collect_properties() self.all_projects.append(p_view) n = self.vsnode_vsdir(self, make_uuid(self.srcnode.abspath() + 'build_aliases'), "build_aliases") p_build.parent = p_install.parent = p_view.parent = n self.all_projects.append(n) def collect_dirs(self): """ Create the folder structure in the CodeLite project view """ seen = {} def make_parents(proj): # look at a project, try to make a parent if getattr(proj, 'parent', None): # aliases already have parents return x = proj.iter_path if x in seen: proj.parent = seen[x] return # There is not vsnode_vsdir for x. # So create a project representing the folder "x" n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.abspath()), x.name) n.iter_path = x.parent self.all_projects.append(n) # recurse up to the project directory if x.height() > self.srcnode.height() + 1: make_parents(n) for p in self.all_projects[:]: # iterate over a copy of all projects if not getattr(p, 'tg', None): # but only projects that have a task generator continue # make a folder for each task generator p.iter_path = p.tg.path make_parents(p) def options(ctx): pass debian/waf-1.7/waflib/extras/fsb.py0000664000000000000000000000107412145745420014154 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Fully sequential builds The previous tasks from task generators are re-processed, and this may lead to speed issues Yet, if you are using this, speed is probably a minor concern """ from waflib import Build def options(opt): pass def configure(conf): pass class FSBContext(Build.BuildContext): def __call__(self, *k, **kw): ret = Build.BuildContext.__call__(self, *k, **kw) # evaluate the results immediately Build.BuildContext.compile(self) return ret def compile(self): pass debian/waf-1.7/waflib/extras/fc_pgfortran.py0000664000000000000000000000342512145745420016056 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_pgfortran') @conf def find_pgfortran(conf): """Find the PGI fortran compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['pgfortran', 'pgf95', 'pgf90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_pgfortran_version(fc) conf.env.FC_NAME = 'PGFC' @conf def pgfortran_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-shared'] v['FCFLAGS_DEBUG'] = ['-Minform=inform', '-Mstandard'] # why not v['FCSTLIB_MARKER'] = '-Bstatic' v['FCSHLIB_MARKER'] = '-Bdynamic' v['SONAME_ST'] = '-soname %s' @conf def get_pgfortran_version(conf,fc): version_re = re.compile(r"The Portland Group", re.I).search cmd = fc + ['-V'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not verify PGI signature') cmd = fc + ['-help=variable'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out.find('COMPVER')<0: conf.fatal('Could not determine the compiler type') k = {} prevk = '' out = out.split('\n') for line in out: lst = line.partition('=') if lst[1] == '=': key = lst[0].rstrip() if key == '': key = prevk val = lst[2].rstrip() k[key] = val else: prevk = line.partition(' ')[0] def isD(var): return var in k def isT(var): return var in k and k[var]!='0' conf.env['FC_VERSION'] = (k['COMPVER'].split('.')) def configure(conf): conf.find_pgfortran() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.pgfortran_flags() debian/waf-1.7/waflib/extras/swig.py0000664000000000000000000001050612145745420014353 0ustar #! /usr/bin/env python # encoding: UTF-8 # Petar Forai # Thomas Nagy 2008-2010 (ita) import re from waflib import Task, Utils, Logs from waflib.TaskGen import extension, feature, after_method from waflib.Configure import conf from waflib.Tools import c_preproc """ tasks have to be added dynamically: - swig interface files may be created at runtime - the module name may be unknown in advance """ SWIG_EXTS = ['.swig', '.i'] re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) re_2 = re.compile('%include "(.*)"', re.M) re_3 = re.compile('#include "(.*)"', re.M) class swig(Task.Task): color = 'BLUE' run_str = '${SWIG} ${SWIGFLAGS} ${SWIGPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${SRC}' ext_out = ['.h'] # might produce .h files although it is not mandatory def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not getattr(self, 'init_outputs', None): self.init_outputs = True if not getattr(self, 'module', None): # search the module name txt = self.inputs[0].read() m = re_module.search(txt) if not m: raise ValueError("could not find the swig module name") self.module = m.group(1) swig_c(self) # add the language-specific output files as nodes # call funs in the dict swig_langs for x in self.env['SWIGFLAGS']: # obtain the language x = x[1:] try: fun = swig_langs[x] except KeyError: pass else: fun(self) return super(swig, self).runnable_status() def scan(self): "scan for swig dependencies, climb the .i files" env = self.env lst_src = [] seen = [] to_see = [self.inputs[0]] while to_see: node = to_see.pop(0) if node in seen: continue seen.append(node) lst_src.append(node) # read the file code = node.read() code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) # find .i files and project headers names = re_2.findall(code) + re_3.findall(code) for n in names: for d in self.generator.includes_nodes + [node.parent]: u = d.find_resource(n) if u: to_see.append(u) break else: Logs.warn('could not find %r' % n) return (lst_src, []) # provide additional language processing swig_langs = {} def swigf(fun): swig_langs[fun.__name__.replace('swig_', '')] = fun swig.swigf = swigf def swig_c(self): ext = '.swigwrap_%d.c' % self.generator.idx flags = self.env['SWIGFLAGS'] if '-c++' in flags: ext += 'xx' out_node = self.inputs[0].parent.find_or_declare(self.module + ext) if '-c++' in flags: c_tsk = self.generator.cxx_hook(out_node) else: c_tsk = self.generator.c_hook(out_node) c_tsk.set_run_after(self) ge = self.generator.bld.producer ge.outstanding.insert(0, c_tsk) ge.total += 1 try: ltask = self.generator.link_task except AttributeError: pass else: ltask.set_run_after(c_tsk) ltask.inputs.append(c_tsk.outputs[0]) self.outputs.append(out_node) if not '-o' in self.env['SWIGFLAGS']: self.env.append_value('SWIGFLAGS', ['-o', self.outputs[0].abspath()]) @swigf def swig_python(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py')) @swigf def swig_ocaml(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.ml')) tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.mli')) @extension(*SWIG_EXTS) def i_file(self, node): # the task instance tsk = self.create_task('swig') tsk.set_inputs(node) tsk.module = getattr(self, 'swig_module', None) flags = self.to_list(getattr(self, 'swig_flags', [])) tsk.env.append_value('SWIGFLAGS', flags) # looks like this is causing problems #if not '-outdir' in flags: # tsk.env.append_value('SWIGFLAGS', ['-outdir', node.parent.abspath()]) @conf def check_swig_version(self): """Check for a minimum swig version like conf.check_swig_version('1.3.28') or conf.check_swig_version((1,3,28)) """ reg_swig = re.compile(r'SWIG Version\s(.*)', re.M) swig_out = self.cmd_and_log('%s -version' % self.env['SWIG']) swigver = tuple([int(s) for s in reg_swig.findall(swig_out)[0].split('.')]) self.env['SWIG_VERSION'] = swigver msg = 'Checking for swig version' self.msg(msg, '.'.join(map(str, swigver))) return swigver def configure(conf): swig = conf.find_program('swig', var='SWIG') conf.env.SWIGPATH_ST = '-I%s' debian/waf-1.7/waflib/extras/midl.py0000664000000000000000000000403112145745420014323 0ustar #!/usr/bin/env python # Issue 1185 ultrix gmail com """ Microsoft Interface Definition Language support. Given ComObject.idl, this tool will generate ComObject.tlb ComObject_i.h ComObject_i.c ComObject_p.c and dlldata.c To declare targets using midl:: def configure(conf): conf.load('msvc') conf.load('midl') def build(bld): bld( features='c cshlib', # Note: ComObject_i.c is generated from ComObject.idl source = 'main.c ComObject.idl ComObject_i.c', target = 'ComObject.dll') """ from waflib import Task, Utils from waflib.TaskGen import feature, before_method import os def configure(conf): conf.find_program(['midl'], var='MIDL') conf.env.MIDLFLAGS = [ '/nologo', '/D', '_DEBUG', '/W1', '/char', 'signed', '/Oicf', ] @feature('c', 'cxx') @before_method('process_source') def idl_file(self): # Do this before process_source so that the generated header can be resolved # when scanning source dependencies. idl_nodes = [] src_nodes = [] for node in Utils.to_list(self.source): if str(node).endswith('.idl'): idl_nodes.append(node) else: src_nodes.append(node) for node in self.to_nodes(idl_nodes): t = node.change_ext('.tlb') h = node.change_ext('_i.h') c = node.change_ext('_i.c') p = node.change_ext('_p.c') d = node.parent.find_or_declare('dlldata.c') tsk = self.create_task('midl', node, [t, h, c, p, d]) self.source = src_nodes class midl(Task.Task): """ Compile idl files """ color = 'YELLOW' run_str = '${MIDL} ${MIDLFLAGS} ${CPPPATH_ST:INCLUDES} /tlb ${TGT[0].bldpath()} /header ${TGT[1].bldpath()} /iid ${TGT[2].bldpath()} /proxy ${TGT[3].bldpath()} /dlldata ${TGT[4].bldpath()} ${SRC}' before = ['winrc'] def exec_command(self, *k, **kw): if self.env['PATH']: env = self.env.env or dict(os.environ) env.update(PATH = ';'.join(self.env['PATH'])) kw['env'] = env bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir return bld.exec_command(k[0], **kw) debian/waf-1.7/waflib/extras/cabal.py0000664000000000000000000001227312145745420014447 0ustar #!/usr/bin/env python # encoding: utf-8 # Anton Feldmann, 2012 # "Base for cabal" import re import time from waflib import TaskGen, Task, Utils from waflib.Configure import conf from waflib.Task import always_run from waflib.TaskGen import extension, feature, after, before, before_method from waflib.Utils import threading from shutil import rmtree lock = threading.Lock() registering = False def configure(self): self.find_program('cabal', var='CABAL') self.find_program('ghc-pkg', var='GHCPKG') pkgconfd = self.bldnode.abspath() + '/package.conf.d' self.env.PREFIX = self.bldnode.abspath() + '/dist' self.env.PKGCONFD = pkgconfd if self.root.find_node(pkgconfd + '/package.cache'): self.msg('Using existing package database', pkgconfd, color='CYAN') else: pkgdir = self.root.find_dir(pkgconfd) if pkgdir: self.msg('Deleting corrupt package database', pkgdir.abspath(), color ='RED') rmtree(pkgdir.abspath()) pkgdir = None self.cmd_and_log([self.env.GHCPKG, 'init', pkgconfd]) self.msg('Created package database', pkgconfd, color = 'YELLOW' if pkgdir else 'GREEN') @extension('.cabal') def process_cabal(self, node): out_dir_node = self.bld.root.find_dir(self.bld.out_dir) package_node = node.change_ext('.package') package_node = out_dir_node.find_or_declare(package_node.name) build_node = node.parent.get_bld() build_path = build_node.abspath() config_node = build_node.find_or_declare('setup-config') inplace_node = build_node.find_or_declare('package.conf.inplace') config_task = self.create_task('cabal_configure', node) config_task.cwd = node.parent.abspath() config_task.depends_on = getattr(self, 'depends_on', '') config_task.build_path = build_path config_task.set_outputs(config_node) build_task = self.create_task('cabal_build', config_node) build_task.cwd = node.parent.abspath() build_task.build_path = build_path build_task.set_outputs(inplace_node) copy_task = self.create_task('cabal_copy', inplace_node) copy_task.cwd = node.parent.abspath() copy_task.depends_on = getattr(self, 'depends_on', '') copy_task.build_path = build_path last_task = copy_task task_list = [config_task, build_task, copy_task] if (getattr(self, 'register', False)): register_task = self.create_task('cabal_register', inplace_node) register_task.cwd = node.parent.abspath() register_task.set_run_after(copy_task) register_task.build_path = build_path pkgreg_task = self.create_task('ghcpkg_register', inplace_node) pkgreg_task.cwd = node.parent.abspath() pkgreg_task.set_run_after(register_task) pkgreg_task.build_path = build_path last_task = pkgreg_task task_list += [register_task, pkgreg_task] touch_task = self.create_task('cabal_touch', inplace_node) touch_task.set_run_after(last_task) touch_task.set_outputs(package_node) touch_task.build_path = build_path task_list += [touch_task] return task_list def get_all_src_deps(node): hs_deps = node.ant_glob('**/*.hs') hsc_deps = node.ant_glob('**/*.hsc') lhs_deps = node.ant_glob('**/*.lhs') c_deps = node.ant_glob('**/*.c') cpp_deps = node.ant_glob('**/*.cpp') proto_deps = node.ant_glob('**/*.proto') return sum([hs_deps, hsc_deps, lhs_deps, c_deps, cpp_deps, proto_deps], []) class Cabal(Task.Task): def scan(self): return (get_all_src_deps(self.generator.path), ()) class cabal_configure(Cabal): run_str = '${CABAL} configure -v0 --prefix=${PREFIX} --global --user --package-db=${PKGCONFD} --builddir=${tsk.build_path}' shell = True def scan(self): out_node = self.generator.bld.root.find_dir(self.generator.bld.out_dir) deps = [out_node.find_or_declare(dep).change_ext('.package') for dep in Utils.to_list(self.depends_on)] return (deps, ()) class cabal_build(Cabal): run_str = '${CABAL} build -v1 --builddir=${tsk.build_path}/' shell = True class cabal_copy(Cabal): run_str = '${CABAL} copy -v0 --builddir=${tsk.build_path}' shell = True class cabal_register(Cabal): run_str = '${CABAL} register -v0 --gen-pkg-config=${tsk.build_path}/pkg.config --builddir=${tsk.build_path}' shell = True class ghcpkg_register(Cabal): run_str = '${GHCPKG} update -v0 --global --user --package-conf=${PKGCONFD} ${tsk.build_path}/pkg.config' shell = True def runnable_status(self): global lock, registering val = False lock.acquire() val = registering lock.release() if val: return Task.ASK_LATER ret = Task.Task.runnable_status(self) if ret == Task.RUN_ME: lock.acquire() registering = True lock.release() return ret def post_run(self): global lock, registering lock.acquire() registering = False lock.release() return Task.Task.post_run(self) class cabal_touch(Cabal): run_str = 'touch ${TGT}' debian/waf-1.7/waflib/extras/relocation.py0000664000000000000000000000435212145745420015543 0ustar #! /usr/bin/env python # encoding: utf-8 """ Waf 1.6 Try to detect if the project directory was relocated, and if it was, change the node representing the project directory. Just call: waf configure build Note that if the project directory name changes, the signatures for the tasks using files in that directory will change, causing a partial build. """ import os from waflib import Build, ConfigSet, Task, Utils, Errors from waflib.TaskGen import feature, before_method, after_method EXTRA_LOCK = '.old_srcdir' old1 = Build.BuildContext.store def store(self): old1(self) db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() env.SRCDIR = self.srcnode.abspath() env.store(db) Build.BuildContext.store = store old2 = Build.BuildContext.init_dirs def init_dirs(self): if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') srcdir = None db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() try: env.load(db) srcdir = env.SRCDIR except: pass if srcdir: d = self.root.find_node(srcdir) if d and srcdir != self.top_dir and getattr(d, 'children', ''): srcnode = self.root.make_node(self.top_dir) print("relocating the source directory %r -> %r" % (srcdir, self.top_dir)) srcnode.children = {} for (k, v) in d.children.items(): srcnode.children[k] = v v.parent = srcnode d.children = {} old2(self) Build.BuildContext.init_dirs = init_dirs def uid(self): try: return self.uid_ except AttributeError: # this is not a real hot zone, but we want to avoid surprises here m = Utils.md5() up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.path_from(x.ctx.srcnode).encode()) self.uid_ = m.digest() return self.uid_ Task.Task.uid = uid @feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) self.includes_nodes = lst bld = self.bld self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.bldnode) or x.abspath() for x in lst] debian/waf-1.7/waflib/extras/compat15.py0000664000000000000000000002210512145745420015031 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ This file is provided to enable compatibility with waf 1.5 It was enabled by default in waf 1.6, but it is not used in waf 1.7 """ import sys from waflib import ConfigSet, Logs, Options, Scripting, Task, Build, Configure, Node, Runner, TaskGen, Utils, Errors, Context # the following is to bring some compatibility with waf 1.5 "import waflib.Configure → import Configure" sys.modules['Environment'] = ConfigSet ConfigSet.Environment = ConfigSet.ConfigSet sys.modules['Logs'] = Logs sys.modules['Options'] = Options sys.modules['Scripting'] = Scripting sys.modules['Task'] = Task sys.modules['Build'] = Build sys.modules['Configure'] = Configure sys.modules['Node'] = Node sys.modules['Runner'] = Runner sys.modules['TaskGen'] = TaskGen sys.modules['Utils'] = Utils from waflib.Tools import c_preproc sys.modules['preproc'] = c_preproc from waflib.Tools import c_config sys.modules['config_c'] = c_config ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive ConfigSet.ConfigSet.set_variant = Utils.nada Build.BuildContext.add_subdirs = Build.BuildContext.recurse Build.BuildContext.new_task_gen = Build.BuildContext.__call__ Build.BuildContext.is_install = 0 Node.Node.relpath_gen = Node.Node.path_from def name_to_obj(self, s, env=None): Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') return self.get_tgen_by_name(s) Build.BuildContext.name_to_obj = name_to_obj def env_of_name(self, name): try: return self.all_envs[name] except KeyError: Logs.error('no such environment: '+name) return None Build.BuildContext.env_of_name = env_of_name def set_env_name(self, name, env): self.all_envs[name] = env return env Configure.ConfigurationContext.set_env_name = set_env_name def retrieve(self, name, fromenv=None): try: env = self.all_envs[name] except KeyError: env = ConfigSet.ConfigSet() self.prepare_env(env) self.all_envs[name] = env else: if fromenv: Logs.warn("The environment %s may have been configured already" % name) return env Configure.ConfigurationContext.retrieve = retrieve Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load Configure.conftest = Configure.conf Configure.ConfigurationError = Errors.ConfigurationError Options.OptionsContext.sub_options = Options.OptionsContext.recurse Options.OptionsContext.tool_options = Context.Context.load Options.Handler = Options.OptionsContext Task.simple_task_type = Task.task_type_from_func = Task.task_factory Task.TaskBase.classes = Task.classes def setitem(self, key, value): if key.startswith('CCFLAGS'): key = key[1:] self.table[key] = value ConfigSet.ConfigSet.__setitem__ = setitem @TaskGen.feature('d') @TaskGen.before('apply_incpaths') def old_importpaths(self): if getattr(self, 'importpaths', []): self.includes = self.importpaths from waflib import Context eld = Context.load_tool def load_tool(*k, **kw): ret = eld(*k, **kw) if 'set_options' in ret.__dict__: Logs.warn('compat: rename "set_options" to options') ret.options = ret.set_options if 'detect' in ret.__dict__: Logs.warn('compat: rename "detect" to "configure"') ret.configure = ret.detect return ret Context.load_tool = load_tool rev = Context.load_module def load_module(path): ret = rev(path) if 'set_options' in ret.__dict__: Logs.warn('compat: rename "set_options" to "options" (%r)' % path) ret.options = ret.set_options if 'srcdir' in ret.__dict__: Logs.warn('compat: rename "srcdir" to "top" (%r)' % path) ret.top = ret.srcdir if 'blddir' in ret.__dict__: Logs.warn('compat: rename "blddir" to "out" (%r)' % path) ret.out = ret.blddir return ret Context.load_module = load_module old_post = TaskGen.task_gen.post def post(self): self.features = self.to_list(self.features) if 'cc' in self.features: Logs.warn('compat: the feature cc does not exist anymore (use "c")') self.features.remove('cc') self.features.append('c') if 'cstaticlib' in self.features: Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') self.features.remove('cstaticlib') self.features.append(('cxx' in self.features) and 'cxxstlib' or 'cstlib') if getattr(self, 'ccflags', None): Logs.warn('compat: "ccflags" was renamed to "cflags"') self.cflags = self.ccflags return old_post(self) TaskGen.task_gen.post = post def waf_version(*k, **kw): Logs.warn('wrong version (waf_version was removed in waf 1.6)') Utils.waf_version = waf_version import os @TaskGen.feature('c', 'cxx', 'd') @TaskGen.before('apply_incpaths', 'propagate_uselib_vars') @TaskGen.after('apply_link', 'process_source') def apply_uselib_local(self): """ process the uselib_local attribute execute after apply_link because of the execution order set on 'link_task' """ env = self.env from waflib.Tools.ccroot import stlink_task # 1. the case of the libs defined in the project (visit ancestors first) # the ancestors external libraries (uselib) will be prepended self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'uselib_local', [])) get = self.bld.get_tgen_by_name seen = set([]) tmp = Utils.deque(names) # consume a copy of the list of names if tmp: Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = get(lib_name) y.post() seen.add(lib_name) # object has ancestors to process (shared libraries): add them to the end of the list if getattr(y, 'uselib_local', None): for x in self.to_list(getattr(y, 'uselib_local', [])): obj = get(x) obj.post() if getattr(obj, 'link_task', None): if not isinstance(obj.link_task, stlink_task): tmp.append(x) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind(os.sep) + 1:] if isinstance(y.link_task, stlink_task): env.append_value('STLIB', [link_name]) else: # some linkers can link against programs env.append_value('LIB', [link_name]) # the order self.link_task.set_run_after(y.link_task) # for the recompilation self.link_task.dep_nodes += y.link_task.outputs # add the link path too tmp_path = y.link_task.outputs[0].parent.bldpath() if not tmp_path in env['LIBPATH']: env.prepend_value('LIBPATH', [tmp_path]) # add ancestors uselib too - but only propagate those that have no staticlib defined for v in self.to_list(getattr(y, 'uselib', [])): if not env['STLIB_' + v]: if not v in self.uselib: self.uselib.insert(0, v) # if the library task generator provides 'export_includes', add to the include path # the export_includes must be a list of paths relative to the other library if getattr(y, 'export_includes', None): self.includes.extend(y.to_incnodes(y.export_includes)) @TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') @TaskGen.after('apply_link') def apply_objdeps(self): "add the .o files produced by some other object files in the same manner as uselib_local" names = getattr(self, 'add_objects', []) if not names: return names = self.to_list(names) get = self.bld.get_tgen_by_name seen = [] while names: x = names[0] # visit dependencies only once if x in seen: names = names[1:] continue # object does not exist ? y = get(x) # object has ancestors to process first ? update the list of names if getattr(y, 'add_objects', None): added = 0 lst = y.to_list(y.add_objects) lst.reverse() for u in lst: if u in seen: continue added = 1 names = [u]+names if added: continue # list of names modified, loop # safe to process the current object y.post() seen.append(x) for t in getattr(y, 'compiled_tasks', []): self.link_task.inputs.extend(t.outputs) @TaskGen.after('apply_link') def process_obj_files(self): if not hasattr(self, 'obj_files'): return for x in self.obj_files: node = self.path.find_resource(x) self.link_task.inputs.append(node) @TaskGen.taskgen_method def add_obj_file(self, file): """Small example on how to link object files as if they were source obj = bld.create_obj('cc') obj.add_obj_file('foo.o')""" if not hasattr(self, 'obj_files'): self.obj_files = [] if not 'process_obj_files' in self.meths: self.meths.append('process_obj_files') self.obj_files.append(file) old_define = Configure.ConfigurationContext.__dict__['define'] @Configure.conf def define(self, key, val, quote=True): old_define(self, key, val, quote) if key.startswith('HAVE_'): self.env[key] = 1 old_undefine = Configure.ConfigurationContext.__dict__['undefine'] @Configure.conf def undefine(self, key): old_undefine(self, key) if key.startswith('HAVE_'): self.env[key] = 0 # some people might want to use export_incdirs, but it was renamed def set_incdirs(self, val): Logs.warn('compat: change "export_incdirs" by "export_includes"') self.export_includes = val TaskGen.task_gen.export_incdirs = property(None, set_incdirs) debian/waf-1.7/waflib/extras/eclipse.py0000664000000000000000000002514412145745420015032 0ustar #! /usr/bin/env python # encoding: utf-8 # Eclipse CDT 5.0 generator for Waf # Richard Quirk 2009-1011 (New BSD License) # Thomas Nagy 2011 (ported to Waf 1.6) """ Usage: def options(opt): opt.load('eclipse') $ waf configure eclipse """ import sys, os from waflib import Utils, Logs, Context, Options, Build, TaskGen, Scripting from xml.dom.minidom import Document oe_cdt = 'org.eclipse.cdt' cdt_mk = oe_cdt + '.make.core' cdt_core = oe_cdt + '.core' cdt_bld = oe_cdt + '.build.core' class eclipse(Build.BuildContext): cmd = 'eclipse' fun = Scripting.default_cmd def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) self.create_cproject(appname, pythonpath=self.env['ECLIPSE_PYTHON_PATH']) def create_cproject(self, appname, workspace_includes=[], pythonpath=[]): """ Create the Eclipse CDT .project and .cproject files @param appname The name that will appear in the Project Explorer @param build The BuildContext object to extract includes from @param workspace_includes Optional project includes to prevent "Unresolved Inclusion" errors in the Eclipse editor @param pythonpath Optional project specific python paths """ source_dirs = [] cpppath = self.env['CPPPATH'] Logs.warn('Generating Eclipse CDT project files') for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue tg.post() if not getattr(tg, 'link_task', None): continue l = Utils.to_list(getattr(tg, "includes", '')) sources = Utils.to_list(getattr(tg, 'source', '')) features = Utils.to_list(getattr(tg, 'features', '')) is_cc = 'c' in features or 'cxx' in features bldpath = tg.path.bldpath() base = os.path.normpath(os.path.join(self.bldnode.name, tg.path.srcpath())) if is_cc: sources_dirs = set([src.parent for src in tg.to_nodes(sources)]) incnodes = tg.to_incnodes(tg.to_list(getattr(tg, 'includes', [])) + tg.env['INCLUDES']) for p in incnodes: path = p.path_from(self.srcnode) workspace_includes.append(path) if is_cc and path not in source_dirs: source_dirs.append(path) project = self.impl_create_project(sys.executable, appname) self.srcnode.make_node('.project').write(project.toprettyxml()) waf = os.path.abspath(sys.argv[0]) project = self.impl_create_cproject(sys.executable, waf, appname, workspace_includes, cpppath, source_dirs) self.srcnode.make_node('.cproject').write(project.toprettyxml()) project = self.impl_create_pydevproject(appname, sys.path, pythonpath) self.srcnode.make_node('.pydevproject').write(project.toprettyxml()) def impl_create_project(self, executable, appname): doc = Document() projectDescription = doc.createElement('projectDescription') self.add(doc, projectDescription, 'name', appname) self.add(doc, projectDescription, 'comment') self.add(doc, projectDescription, 'projects') buildSpec = self.add(doc, projectDescription, 'buildSpec') buildCommand = self.add(doc, buildSpec, 'buildCommand') self.add(doc, buildCommand, 'name', oe_cdt + '.managedbuilder.core.genmakebuilder') self.add(doc, buildCommand, 'triggers', 'clean,full,incremental,') arguments = self.add(doc, buildCommand, 'arguments') # the default make-style targets are overwritten by the .cproject values dictionaries = { cdt_mk + '.contents': cdt_mk + '.activeConfigSettings', cdt_mk + '.enableAutoBuild': 'false', cdt_mk + '.enableCleanBuild': 'true', cdt_mk + '.enableFullBuild': 'true', } for k, v in dictionaries.items(): self.addDictionary(doc, arguments, k, v) natures = self.add(doc, projectDescription, 'natures') nature_list = """ core.ccnature managedbuilder.core.ScannerConfigNature managedbuilder.core.managedBuildNature core.cnature """.split() for n in nature_list: self.add(doc, natures, 'nature', oe_cdt + '.' + n) self.add(doc, natures, 'nature', 'org.python.pydev.pythonNature') doc.appendChild(projectDescription) return doc def impl_create_cproject(self, executable, waf, appname, workspace_includes, cpppath, source_dirs=[]): doc = Document() doc.appendChild(doc.createProcessingInstruction('fileVersion', '4.0.0')) cconf_id = cdt_core + '.default.config.1' cproject = doc.createElement('cproject') storageModule = self.add(doc, cproject, 'storageModule', {'moduleId': cdt_core + '.settings'}) cconf = self.add(doc, storageModule, 'cconfiguration', {'id':cconf_id}) storageModule = self.add(doc, cconf, 'storageModule', {'buildSystemId': oe_cdt + '.managedbuilder.core.configurationDataProvider', 'id': cconf_id, 'moduleId': cdt_core + '.settings', 'name': 'Default'}) self.add(doc, storageModule, 'externalSettings') extensions = self.add(doc, storageModule, 'extensions') extension_list = """ VCErrorParser MakeErrorParser GCCErrorParser GASErrorParser GLDErrorParser """.split() ext = self.add(doc, extensions, 'extension', {'id': cdt_core + '.ELF', 'point':cdt_core + '.BinaryParser'}) for e in extension_list: ext = self.add(doc, extensions, 'extension', {'id': cdt_core + '.' + e, 'point':cdt_core + '.ErrorParser'}) storageModule = self.add(doc, cconf, 'storageModule', {'moduleId': 'cdtBuildSystem', 'version': '4.0.0'}) config = self.add(doc, storageModule, 'configuration', {'artifactName': appname, 'id': cconf_id, 'name': 'Default', 'parent': cdt_bld + '.prefbase.cfg'}) folderInfo = self.add(doc, config, 'folderInfo', {'id': cconf_id+'.', 'name': '/', 'resourcePath': ''}) toolChain = self.add(doc, folderInfo, 'toolChain', {'id': cdt_bld + '.prefbase.toolchain.1', 'name': 'No ToolChain', 'resourceTypeBasedDiscovery': 'false', 'superClass': cdt_bld + '.prefbase.toolchain'}) targetPlatform = self.add(doc, toolChain, 'targetPlatform', { 'binaryParser': 'org.eclipse.cdt.core.ELF', 'id': cdt_bld + '.prefbase.toolchain.1', 'name': ''}) waf_build = '"%s" %s'%(waf, eclipse.fun) waf_clean = '"%s" clean'%(waf) builder = self.add(doc, toolChain, 'builder', {'autoBuildTarget': waf_build, 'command': executable, 'enableAutoBuild': 'false', 'cleanBuildTarget': waf_clean, 'enableIncrementalBuild': 'true', 'id': cdt_bld + '.settings.default.builder.1', 'incrementalBuildTarget': waf_build, 'managedBuildOn': 'false', 'name': 'Gnu Make Builder', 'superClass': cdt_bld + '.settings.default.builder'}) for tool_name in ("Assembly", "GNU C++", "GNU C"): tool = self.add(doc, toolChain, 'tool', {'id': cdt_bld + '.settings.holder.1', 'name': tool_name, 'superClass': cdt_bld + '.settings.holder'}) if cpppath or workspace_includes: incpaths = cdt_bld + '.settings.holder.incpaths' option = self.add(doc, tool, 'option', {'id': incpaths+'.1', 'name': 'Include Paths', 'superClass': incpaths, 'valueType': 'includePath'}) for i in workspace_includes: self.add(doc, option, 'listOptionValue', {'builtIn': 'false', 'value': '"${workspace_loc:/%s/%s}"'%(appname, i)}) for i in cpppath: self.add(doc, option, 'listOptionValue', {'builtIn': 'false', 'value': '"%s"'%(i)}) if source_dirs: sourceEntries = self.add(doc, config, 'sourceEntries') for i in source_dirs: self.add(doc, sourceEntries, 'entry', {'excluding': i, 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind': 'sourcePath', 'name': ''}) self.add(doc, sourceEntries, 'entry', { 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind': 'sourcePath', 'name': i}) storageModule = self.add(doc, cconf, 'storageModule', {'moduleId': cdt_mk + '.buildtargets'}) buildTargets = self.add(doc, storageModule, 'buildTargets') def addTargetWrap(name, runAll): return self.addTarget(doc, buildTargets, executable, name, '"%s" %s'%(waf, name), runAll) addTargetWrap('configure', True) addTargetWrap('dist', False) addTargetWrap('install', False) addTargetWrap('check', False) storageModule = self.add(doc, cproject, 'storageModule', {'moduleId': 'cdtBuildSystem', 'version': '4.0.0'}) project = self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname}) doc.appendChild(cproject) return doc def impl_create_pydevproject(self, appname, system_path, user_path): # create a pydevproject file doc = Document() doc.appendChild(doc.createProcessingInstruction('eclipse-pydev', 'version="1.0"')) pydevproject = doc.createElement('pydev_project') prop = self.add(doc, pydevproject, 'pydev_property', 'python %d.%d'%(sys.version_info[0], sys.version_info[1])) prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_VERSION') prop = self.add(doc, pydevproject, 'pydev_property', 'Default') prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_INTERPRETER') # add waf's paths wafadmin = [p for p in system_path if p.find('wafadmin') != -1] if wafadmin: prop = self.add(doc, pydevproject, 'pydev_pathproperty', {'name':'org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH'}) for i in wafadmin: self.add(doc, prop, 'path', i) if user_path: prop = self.add(doc, pydevproject, 'pydev_pathproperty', {'name':'org.python.pydev.PROJECT_SOURCE_PATH'}) for i in user_path: self.add(doc, prop, 'path', '/'+appname+'/'+i) doc.appendChild(pydevproject) return doc def addDictionary(self, doc, parent, k, v): dictionary = self.add(doc, parent, 'dictionary') self.add(doc, dictionary, 'key', k) self.add(doc, dictionary, 'value', v) return dictionary def addTarget(self, doc, buildTargets, executable, name, buildTarget, runAllBuilders=True): target = self.add(doc, buildTargets, 'target', {'name': name, 'path': '', 'targetID': oe_cdt + '.build.MakeTargetBuilder'}) self.add(doc, target, 'buildCommand', executable) self.add(doc, target, 'buildArguments', None) self.add(doc, target, 'buildTarget', buildTarget) self.add(doc, target, 'stopOnError', 'true') self.add(doc, target, 'useDefaultCommand', 'false') self.add(doc, target, 'runAllBuilders', str(runAllBuilders).lower()) def add(self, doc, parent, tag, value = None): el = doc.createElement(tag) if (value): if type(value) == type(str()): el.appendChild(doc.createTextNode(value)) elif type(value) == type(dict()): self.setAttributes(el, value) parent.appendChild(el) return el def setAttributes(self, node, attrs): for k, v in attrs.items(): node.setAttribute(k, v) debian/waf-1.7/waflib/extras/objcopy.py0000664000000000000000000000332612145745420015051 0ustar #!/usr/bin/python # Grygoriy Fuchedzhy 2010 """ Support for converting linked targets to ihex, srec or binary files using objcopy. Use the 'objcopy' feature in conjuction with the 'cc' or 'cxx' feature. The 'objcopy' feature uses the following attributes: objcopy_bfdname Target object format name (eg. ihex, srec, binary). Defaults to ihex. objcopy_target File name used for objcopy output. This defaults to the target name with objcopy_bfdname as extension. objcopy_install_path Install path for objcopy_target file. Defaults to ${PREFIX}/fw. objcopy_flags Additional flags passed to objcopy. """ from waflib.Utils import def_attrs from waflib import Task from waflib.TaskGen import feature, after_method class objcopy(Task.Task): run_str = '${OBJCOPY} -O ${TARGET_BFDNAME} ${OBJCOPYFLAGS} ${SRC} ${TGT}' color = 'CYAN' @feature('objcopy') @after_method('apply_link') def objcopy(self): def_attrs(self, objcopy_bfdname = 'ihex', objcopy_target = None, objcopy_install_path = "${PREFIX}/firmware", objcopy_flags = '') link_output = self.link_task.outputs[0] if not self.objcopy_target: self.objcopy_target = link_output.change_ext('.' + self.objcopy_bfdname).name task = self.create_task('objcopy', src=link_output, tgt=self.path.find_or_declare(self.objcopy_target)) task.env.append_unique('TARGET_BFDNAME', self.objcopy_bfdname) try: task.env.append_unique('OBJCOPYFLAGS', getattr(self, 'objcopy_flags')) except AttributeError: pass if self.objcopy_install_path: self.bld.install_files(self.objcopy_install_path, task.outputs[0], env=task.env.derive()) def configure(ctx): objcopy = ctx.find_program('objcopy', var='OBJCOPY', mandatory=True) debian/waf-1.7/waflib/extras/sync_exec.py0000664000000000000000000000017112145745420015357 0ustar #! /usr/bin/env python # encoding: utf-8 """ This tool is obsolete, the sync_exec feature is now the default """ pass debian/waf-1.7/waflib/extras/go.py0000664000000000000000000001726512145745420014020 0ustar #!/usr/bin/env python # encoding: utf-8 # Tom Wambold tom5760 gmail.com 2009 # Thomas Nagy 2010 """ Go as a language may look nice, but its toolchain is one of the worse a developer has ever seen. It keeps changing though, and I would like to believe that it will get better eventually, but the crude reality is that this tool and the examples are getting broken every few months. If you have been lured into trying to use Go, you should stick to their Makefiles. """ import os, platform from waflib import Utils, Task, TaskGen from waflib.TaskGen import feature, extension, after_method, before_method from waflib.Tools.ccroot import link_task, stlink_task, propagate_uselib_vars, process_use class go(Task.Task): run_str = '${GOC} ${GOCFLAGS} ${CPPPATH_ST:INCPATHS} -o ${TGT} ${SRC}' class gopackage(stlink_task): run_str = '${GOP} grc ${TGT} ${SRC}' class goprogram(link_task): run_str = '${GOL} ${GOLFLAGS} -o ${TGT} ${SRC}' inst_to = '${BINDIR}' chmod = Utils.O755 class cgopackage(stlink_task): color = 'YELLOW' inst_to = '${LIBDIR}' ext_in = ['.go'] ext_out = ['.a'] def run(self): src_dir = self.generator.bld.path source = self.inputs target = self.outputs[0].change_ext('') #print ("--> %s" % self.outputs) #print ('++> %s' % self.outputs[1]) bld_dir = self.outputs[1] bld_dir.mkdir() obj_dir = bld_dir.make_node('_obj') obj_dir.mkdir() bld_srcs = [] for s in source: # FIXME: it seems gomake/cgo stumbles on filenames like a/b/c.go # -> for the time being replace '/' with '_'... #b = bld_dir.make_node(s.path_from(src_dir)) b = bld_dir.make_node(s.path_from(src_dir).replace(os.sep,'_')) b.parent.mkdir() #print ('++> %s' % (s.path_from(src_dir),)) try: try:os.remove(b.abspath()) except Exception:pass os.symlink(s.abspath(), b.abspath()) except Exception: # if no support for symlinks, copy the file from src b.write(s.read()) bld_srcs.append(b) #print("--|> [%s]" % b.abspath()) b.sig = Utils.h_file(b.abspath()) pass #self.set_inputs(bld_srcs) #self.generator.bld.raw_deps[self.uid()] = [self.signature()] + bld_srcs makefile_node = bld_dir.make_node("Makefile") makefile_tmpl = '''\ # Copyright 2009 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. --- include $(GOROOT)/src/Make.inc TARG=%(target)s GCIMPORTS= %(gcimports)s CGOFILES=\\ \t%(source)s CGO_CFLAGS= %(cgo_cflags)s CGO_LDFLAGS= %(cgo_ldflags)s include $(GOROOT)/src/Make.pkg %%: install %%.go $(GC) $*.go $(LD) -o $@ $*.$O ''' % { 'gcimports': ' '.join(l for l in self.env['GOCFLAGS']), 'cgo_cflags' : ' '.join(l for l in self.env['GOCFLAGS']), 'cgo_ldflags': ' '.join(l for l in self.env['GOLFLAGS']), 'target': target.path_from(obj_dir), 'source': ' '.join([b.path_from(bld_dir) for b in bld_srcs]) } makefile_node.write(makefile_tmpl) #print ("::makefile: %s"%makefile_node.abspath()) cmd = Utils.subst_vars('gomake ${GOMAKE_FLAGS}', self.env).strip() o = self.outputs[0].change_ext('.gomake.log') fout_node = bld_dir.find_or_declare(o.name) fout = open(fout_node.abspath(), 'w') rc = self.generator.bld.exec_command( cmd, stdout=fout, stderr=fout, cwd=bld_dir.abspath(), ) if rc != 0: import waflib.Logs as msg msg.error('** error running [%s] (cgo-%s)' % (cmd, target)) msg.error(fout_node.read()) return rc self.generator.bld.read_stlib( target, paths=[obj_dir.abspath(),], ) tgt = self.outputs[0] if tgt.parent != obj_dir: install_dir = os.path.join('${LIBDIR}', tgt.parent.path_from(obj_dir)) else: install_dir = '${LIBDIR}' #print('===> %s (%s)' % (tgt.abspath(), install_dir)) self.generator.bld.install_files( install_dir, tgt.abspath(), relative_trick=False, postpone=False, ) return rc @extension('.go') def compile_go(self, node): #print('*'*80, self.name) if not ('cgopackage' in self.features): return self.create_compiled_task('go', node) #print ('compile_go-cgo...') bld_dir = node.parent.get_bld() obj_dir = bld_dir.make_node('_obj') target = obj_dir.make_node(node.change_ext('.a').name) return self.create_task('cgopackage', node, node.change_ext('.a')) @feature('gopackage', 'goprogram', 'cgopackage') @before_method('process_source') def go_compiler_is_foobar(self): if self.env.GONAME == 'gcc': return self.source = self.to_nodes(self.source) src = [] go = [] for node in self.source: if node.name.endswith('.go'): go.append(node) else: src.append(node) self.source = src if not ('cgopackage' in self.features): #print('--> [%s]... (%s)' % (go[0], getattr(self, 'target', 'N/A'))) tsk = self.create_compiled_task('go', go[0]) tsk.inputs.extend(go[1:]) else: #print ('+++ [%s] +++' % self.target) bld_dir = self.path.get_bld().make_node('cgopackage--%s' % self.target.replace(os.sep,'_')) obj_dir = bld_dir.make_node('_obj') target = obj_dir.make_node(self.target+'.a') tsk = self.create_task('cgopackage', go, [target, bld_dir]) self.link_task = tsk @feature('gopackage', 'goprogram', 'cgopackage') @after_method('process_source', 'apply_incpaths',) def go_local_libs(self): names = self.to_list(getattr(self, 'use', [])) #print ('== go-local-libs == [%s] == use: %s' % (self.name, names)) for name in names: tg = self.bld.get_tgen_by_name(name) if not tg: raise Utils.WafError('no target of name %r necessary for %r in go uselib local' % (name, self)) tg.post() #print ("-- tg[%s]: %s" % (self.name,name)) lnk_task = getattr(tg, 'link_task', None) if lnk_task: for tsk in self.tasks: if isinstance(tsk, (go, gopackage, cgopackage)): tsk.set_run_after(lnk_task) tsk.dep_nodes.extend(lnk_task.outputs) path = lnk_task.outputs[0].parent.abspath() if isinstance(lnk_task, (go, gopackage)): # handle hierarchical packages path = lnk_task.generator.path.get_bld().abspath() elif isinstance(lnk_task, (cgopackage,)): # handle hierarchical cgopackages cgo_obj_dir = lnk_task.outputs[1].find_or_declare('_obj') path = cgo_obj_dir.abspath() # recursively add parent GOCFLAGS... self.env.append_unique('GOCFLAGS', getattr(lnk_task.env, 'GOCFLAGS',[])) # ditto for GOLFLAGS... self.env.append_unique('GOLFLAGS', getattr(lnk_task.env, 'GOLFLAGS',[])) self.env.append_unique('GOCFLAGS', ['-I%s' % path]) self.env.append_unique('GOLFLAGS', ['-L%s' % path]) for n in getattr(tg, 'includes_nodes', []): self.env.append_unique('GOCFLAGS', ['-I%s' % n.abspath()]) pass pass def configure(conf): def set_def(var, val): if not conf.env[var]: conf.env[var] = val goarch = os.getenv('GOARCH') if goarch == '386': set_def('GO_PLATFORM', 'i386') elif goarch == 'amd64': set_def('GO_PLATFORM', 'x86_64') elif goarch == 'arm': set_def('GO_PLATFORM', 'arm') else: set_def('GO_PLATFORM', platform.machine()) if conf.env.GO_PLATFORM == 'x86_64': set_def('GO_COMPILER', '6g') set_def('GO_LINKER', '6l') elif conf.env.GO_PLATFORM in ['i386', 'i486', 'i586', 'i686']: set_def('GO_COMPILER', '8g') set_def('GO_LINKER', '8l') elif conf.env.GO_PLATFORM == 'arm': set_def('GO_COMPILER', '5g') set_def('GO_LINKER', '5l') set_def('GO_EXTENSION', '.5') if not (conf.env.GO_COMPILER or conf.env.GO_LINKER): raise conf.fatal('Unsupported platform ' + platform.machine()) set_def('GO_PACK', 'gopack') set_def('gopackage_PATTERN', '%s.a') set_def('CPPPATH_ST', '-I%s') set_def('GOMAKE_FLAGS', ['--quiet']) conf.find_program(conf.env.GO_COMPILER, var='GOC') conf.find_program(conf.env.GO_LINKER, var='GOL') conf.find_program(conf.env.GO_PACK, var='GOP') conf.find_program('cgo', var='CGO') TaskGen.feature('go')(process_use) TaskGen.feature('go')(propagate_uselib_vars) debian/waf-1.7/waflib/extras/boost.py0000664000000000000000000002747412145745420014544 0ustar #!/usr/bin/env python # encoding: utf-8 # # partially based on boost.py written by Gernot Vormayr # written by Ruediger Sonderfeld , 2008 # modified by Bjoern Michaelsen, 2008 # modified by Luca Fossati, 2008 # rewritten for waf 1.5.1, Thomas Nagy, 2008 # rewritten for waf 1.6.2, Sylvain Rouquette, 2011 ''' This is an extra tool, not bundled with the default waf binary. To add the boost tool to the waf file: $ ./waf-light --tools=compat15,boost or, if you have waf >= 1.6.2 $ ./waf update --files=boost When using this tool, the wscript will look like: def options(opt): opt.load('compiler_cxx boost') def configure(conf): conf.load('compiler_cxx boost') conf.check_boost(lib='system filesystem') def build(bld): bld(source='main.cpp', target='app', use='BOOST') Options are generated, in order to specify the location of boost includes/libraries. The `check_boost` configuration function allows to specify the used boost libraries. It can also provide default arguments to the --boost-static and --boost-mt command-line arguments. Everything will be packaged together in a BOOST component that you can use. When using MSVC, a lot of compilation flags need to match your BOOST build configuration: - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined. Errors: C4530 - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC So before calling `conf.check_boost` you might want to disabling by adding: conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB'] Errors: - boost might also be compiled with /MT, which links the runtime statically. If you have problems with redefined symbols, self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc'] Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases. ''' import sys import re from waflib import Utils, Logs, Errors from waflib.Configure import conf BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] BOOST_VERSION_FILE = 'boost/version.hpp' BOOST_VERSION_CODE = ''' #include #include int main() { std::cout << BOOST_LIB_VERSION << std::endl; } ''' # toolsets from {boost_dir}/tools/build/v2/tools/common.jam PLATFORM = Utils.unversioned_sys_platform() detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il' detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang' detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc' BOOST_TOOLSETS = { 'borland': 'bcb', 'clang': detect_clang, 'como': 'como', 'cw': 'cw', 'darwin': 'xgcc', 'edg': 'edg', 'g++': detect_mingw, 'gcc': detect_mingw, 'icpc': detect_intel, 'intel': detect_intel, 'kcc': 'kcc', 'kylix': 'bck', 'mipspro': 'mp', 'mingw': 'mgw', 'msvc': 'vc', 'qcc': 'qcc', 'sun': 'sw', 'sunc++': 'sw', 'tru64cxx': 'tru', 'vacpp': 'xlc' } def options(opt): opt.add_option('--boost-includes', type='string', default='', dest='boost_includes', help='''path to the boost includes root (~boost root) e.g. /path/to/boost_1_47_0''') opt.add_option('--boost-libs', type='string', default='', dest='boost_libs', help='''path to the directory where the boost libs are e.g. /path/to/boost_1_47_0/stage/lib''') opt.add_option('--boost-static', action='store_true', default=False, dest='boost_static', help='link with static boost libraries (.lib/.a)') opt.add_option('--boost-mt', action='store_true', default=False, dest='boost_mt', help='select multi-threaded libraries') opt.add_option('--boost-abi', type='string', default='', dest='boost_abi', help='''select libraries with tags (dgsyp, d for debug), see doc Boost, Getting Started, chapter 6.1''') opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect', help="auto-detect boost linkage options (don't get used to it / might break other stuff)") opt.add_option('--boost-toolset', type='string', default='', dest='boost_toolset', help='force a toolset e.g. msvc, vc90, \ gcc, mingw, mgw45 (default: auto)') py_version = '%d%d' % (sys.version_info[0], sys.version_info[1]) opt.add_option('--boost-python', type='string', default=py_version, dest='boost_python', help='select the lib python with this version \ (default: %s)' % py_version) @conf def __boost_get_version_file(self, dir): try: return self.root.find_dir(dir).find_node(BOOST_VERSION_FILE) except: return None @conf def boost_get_version(self, dir): """silently retrieve the boost version number""" re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"$', re.M) try: val = re_but.search(self.__boost_get_version_file(dir).read()).group(1) except: val = self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[dir], execute=False, define_ret=True) return val @conf def boost_get_includes(self, *k, **kw): includes = k and k[0] or kw.get('includes', None) if includes and self.__boost_get_version_file(includes): return includes for dir in BOOST_INCLUDES: if self.__boost_get_version_file(dir): return dir if includes: self.end_msg('headers not found in %s' % includes) self.fatal('The configuration failed') else: self.end_msg('headers not found, please provide a --boost-includes argument (see help)') self.fatal('The configuration failed') @conf def boost_get_toolset(self, cc): toolset = cc if not cc: build_platform = Utils.unversioned_sys_platform() if build_platform in BOOST_TOOLSETS: cc = build_platform else: cc = self.env.CXX_NAME if cc in BOOST_TOOLSETS: toolset = BOOST_TOOLSETS[cc] return isinstance(toolset, str) and toolset or toolset(self.env) @conf def __boost_get_libs_path(self, *k, **kw): ''' return the lib path and all the files in it ''' if 'files' in kw: return self.root.find_dir('.'), Utils.to_list(kw['files']) libs = k and k[0] or kw.get('libs', None) if libs: path = self.root.find_dir(libs) files = path.ant_glob('*boost_*') if not libs or not files: for dir in BOOST_LIBS: try: path = self.root.find_dir(dir) files = path.ant_glob('*boost_*') if files: break path = self.root.find_dir(dir + '64') files = path.ant_glob('*boost_*') if files: break except: path = None if not path: if libs: self.end_msg('libs not found in %s' % libs) self.fatal('The configuration failed') else: self.end_msg('libs not found, please provide a --boost-libs argument (see help)') self.fatal('The configuration failed') self.to_log('Found the boost path in %r with the libraries:' % path) for x in files: self.to_log(' %r' % x) return path, files @conf def boost_get_libs(self, *k, **kw): ''' return the lib path and the required libs according to the parameters ''' path, files = self.__boost_get_libs_path(**kw) t = [] if kw.get('mt', False): t.append('mt') if kw.get('abi', None): t.append(kw['abi']) tags = t and '(-%s)+' % '-'.join(t) or '' toolset = self.boost_get_toolset(kw.get('toolset', '')) toolset_pat = '(-%s[0-9]{0,3})+' % toolset version = '(-%s)+' % self.env.BOOST_VERSION def find_lib(re_lib, files): for file in files: if re_lib.search(file.name): self.to_log('Found boost lib %s' % file) return file return None def format_lib_name(name): if name.startswith('lib') and self.env.CC_NAME != 'msvc': name = name[3:] return name[:name.rfind('.')] libs = [] for lib in Utils.to_list(k and k[0] or kw.get('lib', None)): py = (lib == 'python') and '(-py%s)+' % kw['python'] or '' # Trying libraries, from most strict match to least one for pattern in ['boost_%s%s%s%s%s' % (lib, toolset_pat, tags, py, version), 'boost_%s%s%s%s' % (lib, tags, py, version), 'boost_%s%s%s' % (lib, tags, version), # Give up trying to find the right version 'boost_%s%s%s%s' % (lib, toolset_pat, tags, py), 'boost_%s%s%s' % (lib, tags, py), 'boost_%s%s' % (lib, tags)]: self.to_log('Trying pattern %s' % pattern) file = find_lib(re.compile(pattern), files) if file: libs.append(format_lib_name(file.name)) break else: self.end_msg('lib %s not found in %s' % (lib, path.abspath())) self.fatal('The configuration failed') return path.abspath(), libs @conf def check_boost(self, *k, **kw): """ Initialize boost libraries to be used. Keywords: you can pass the same parameters as with the command line (without "--boost-"). Note that the command line has the priority, and should preferably be used. """ if not self.env['CXX']: self.fatal('load a c++ compiler first, conf.load("compiler_cxx")') params = {'lib': k and k[0] or kw.get('lib', None)} for key, value in self.options.__dict__.items(): if not key.startswith('boost_'): continue key = key[len('boost_'):] params[key] = value and value or kw.get(key, '') var = kw.get('uselib_store', 'BOOST') self.start_msg('Checking boost includes') self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params) self.env.BOOST_VERSION = self.boost_get_version(inc) self.end_msg(self.env.BOOST_VERSION) if Logs.verbose: Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var]) if not params['lib']: return self.start_msg('Checking boost libs') suffix = params.get('static', None) and 'ST' or '' path, libs = self.boost_get_libs(**params) self.env['%sLIBPATH_%s' % (suffix, var)] = [path] self.env['%sLIB_%s' % (suffix, var)] = libs self.end_msg('ok') if Logs.verbose: Logs.pprint('CYAN', ' path : %s' % path) Logs.pprint('CYAN', ' libs : %s' % libs) def try_link(): if 'system' in params['lib']: self.check_cxx( fragment="\n".join([ '#include ', 'int main() { boost::system::error_code c; }', ]), use=var, execute=False, ) if 'thread' in params['lib']: self.check_cxx( fragment="\n".join([ '#include ', 'int main() { boost::thread t; }', ]), use=var, execute=False, ) if params.get('linkage_autodetect', False): self.start_msg("Attempting to detect boost linkage flags") toolset = self.boost_get_toolset(kw.get('toolset', '')) if toolset in ['vc']: # disable auto-linking feature, causing error LNK1181 # because the code wants to be linked against self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] # if no dlls are present, we guess the .lib files are not stubs has_dlls = False for x in Utils.listdir(path): if x.endswith(self.env.cxxshlib_PATTERN % ''): has_dlls = True break if not has_dlls: self.env['STLIBPATH_%s' % var] = [path] self.env['STLIB_%s' % var] = libs del self.env['LIB_%s' % var] del self.env['LIBPATH_%s' % var] # we attempt to play with some known-to-work CXXFLAGS combinations for cxxflags in (['/MD', '/EHsc'], []): self.env.stash() self.env["CXXFLAGS_%s" % var] += cxxflags try: try_link() self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var])) e = None break except Errors.ConfigurationError as exc: self.env.revert() e = exc if e is not None: self.end_msg("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=e) self.fatal('The configuration failed') else: self.end_msg("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain") self.fatal('The configuration failed') else: self.start_msg('Checking for boost linkage') try: try_link() except Errors.ConfigurationError as e: self.end_msg("Could not link against boost libraries using supplied options") self.fatal('The configuration failed') self.end_msg('ok') debian/waf-1.7/waflib/extras/erlang.py0000664000000000000000000000055312145745420014653 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Erlang support """ from waflib import TaskGen TaskGen.declare_chain(name = 'erlc', rule = '${ERLC} ${ERLC_FLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}', ext_in = '.erl', ext_out = '.beam') def configure(conf): conf.find_program('erlc', var='ERLC') conf.env.ERLC_FLAGS = [] debian/waf-1.7/waflib/extras/package.py0000664000000000000000000000306512145745420014777 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 """ Obtain packages, unpack them in a location, and add associated uselib variables (CFLAGS_pkgname, LIBPATH_pkgname, etc). The default is use a Dependencies.txt file in the source directory. This is a work in progress. Usage: def options(opt): opt.load('package') def configure(conf): conf.load_packages() """ from waflib import Logs from waflib.Configure import conf try: from urllib import request except: from urllib import urlopen else: urlopen = request.urlopen CACHEVAR = 'WAFCACHE_PACKAGE' @conf def get_package_cache_dir(self): cache = None if CACHEVAR in conf.environ: cache = conf.environ[CACHEVAR] cache = self.root.make_node(cache) elif self.env[CACHEVAR]: cache = self.env[CACHEVAR] cache = self.root.make_node(cache) else: cache = self.srcnode.make_node('.wafcache_package') cache.mkdir() return cache @conf def download_archive(self, src, dst): for x in self.env.PACKAGE_REPO: url = '/'.join((x, src)) try: web = urlopen(url) try: if web.getcode() != 200: continue except AttributeError: pass except Exception: # on python3 urlopen throws an exception # python 2.3 does not have getcode and throws an exception to fail continue else: tmp = self.root.make_node(dst) tmp.write(web.read()) Logs.warn('Downloaded %s from %s' % (tmp.abspath(), url)) break else: self.fatal('Could not get the package %s' % src) @conf def load_packages(self): cache = self.get_package_cache_dir() # read the dependencies, get the archives, .. debian/waf-1.7/waflib/extras/dcc.py0000664000000000000000000000414012145745420014130 0ustar #!/usr/bin/env python # encoding: utf-8 # Jérôme Carretero, 2011 (zougloub) from waflib import Configure, Options, Utils from waflib.Tools import ccroot from waflib.Configure import conf @conf def find_dcc(conf): cc = conf.find_program(['dcc'], var='CC', path_list=getattr(Options.options, 'diabbindir', "")) cc = conf.cmd_to_list(cc) conf.env.CC_NAME = 'dcc' conf.env.CC = cc @conf def find_dld(conf): ld = conf.find_program(['dld'], var='LINK_CC', path_list=getattr(Options.options, 'diabbindir', "")) ld = conf.cmd_to_list(ld) conf.env.LINK_CC_NAME = 'dld' conf.env.LINK_CC = ld @conf def find_dar(conf): ar = conf.find_program(['dar'], var='DAR', path_list=getattr(Options.options, 'diabbindir', "")) ar = conf.cmd_to_list(ar) conf.env.AR = ar conf.env.AR_NAME = 'dar' conf.env.ARFLAGS = 'rcs' @conf def find_ddump(conf): prg = conf.find_program(['ddump'], var='DDUMP', path_list=getattr(Options.options, 'diabbindir', "")) prg = conf.cmd_to_list(prg) conf.env.DDUMP = prg @conf def dcc_common_flags(conf): v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l:%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l:%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' #v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cprogram_PATTERN'] = '%s.elf' # static lib v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_dcc() conf.find_dar() conf.find_dld() conf.find_ddump() conf.dcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() def options(opt): """ Add the ``--with-diab-bindir`` command-line options. """ opt.add_option('--with-diab-bindir', type='string', dest='diabbindir', help = 'Specify alternate diab bin folder', default="") debian/waf-1.7/waflib/extras/fc_nag.py0000664000000000000000000000272312145745420014621 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].insert(0, 'fc_nag') @conf def find_nag(conf): """Find the NAG Fortran Compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['nagfor'], var='FC') fc = conf.cmd_to_list(fc) conf.get_nag_version(fc) conf.env.FC_NAME = 'NAG' conf.env.FC_MOD_CAPITALIZATION = 'lower' @conf def nag_flags(conf): v = conf.env v['FCFLAGS_DEBUG'] = ['-C=all'] @conf def nag_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() nag_modifier_func = getattr(conf, 'nag_modifier_' + dest_os, None) if nag_modifier_func: nag_modifier_func() @conf def get_nag_version(conf, fc): """Get the NAG compiler version""" version_re = re.compile(r"^NAG Fortran Compiler *Release *(?P\d*)\.(?P\d*)", re.M).search cmd = fc + ['-v'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) if not match: match = version_re(err) else: match = version_re(err) if not match: conf.fatal('Could not determine the NAG version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_nag() conf.find_ar() conf.fc_flags() conf.fc_add_flags() conf.nag_flags() conf.nag_modifier_platform() debian/waf-1.7/waflib/extras/proc.py0000664000000000000000000000340512145745420014345 0ustar #! /usr/bin/env python # per rosengren 2011 from os import environ, path from waflib import TaskGen, Utils def options(opt): grp = opt.add_option_group('Oracle ProC Options') grp.add_option('--oracle_home', action='store', default=environ.get('PROC_ORACLE'), help='Path to Oracle installation home (has bin/lib)') grp.add_option('--tns_admin', action='store', default=environ.get('TNS_ADMIN'), help='Directory containing server list (TNS_NAMES.ORA)') grp.add_option('--connection', action='store', default='dummy-user/dummy-password@dummy-server', help='Format: user/password@server') def configure(cnf): env = cnf.env if not env.PROC_ORACLE: env.PROC_ORACLE = cnf.options.oracle_home if not env.PROC_TNS_ADMIN: env.PROC_TNS_ADMIN = cnf.options.tns_admin if not env.PROC_CONNECTION: env.PROC_CONNECTION = cnf.options.connection cnf.find_program('proc', var='PROC', path_list=env.PROC_ORACLE + path.sep + 'bin') def proc(tsk): env = tsk.env gen = tsk.generator bld = gen.bld inc_nodes = gen.to_incnodes(Utils.to_list(getattr(gen,'includes',[])) + env['INCLUDES']) # FIXME the if-else construct will not work in python 2 cmd = ( [env.PROC] + ['SQLCHECK=SEMANTICS'] + (['SYS_INCLUDE=(' + ','.join(env.PROC_INCLUDES) + ')'] if env.PROC_INCLUDES else []) + ['INCLUDE=(' + ','.join( [i.bldpath() for i in inc_nodes] ) + ')'] + ['userid=' + env.PROC_CONNECTION] + ['INAME=' + tsk.inputs[0].bldpath()] + ['ONAME=' + tsk.outputs[0].bldpath()] ) exec_env = { 'ORACLE_HOME': env.PROC_ORACLE, 'LD_LIBRARY_PATH': env.PROC_ORACLE + path.sep + 'lib', } if env.PROC_TNS_ADMIN: exec_env['TNS_ADMIN'] = env.PROC_TNS_ADMIN return tsk.exec_command(cmd, env=exec_env) TaskGen.declare_chain( name = 'proc', rule = proc, ext_in = '.pc', ext_out = '.c', ) debian/waf-1.7/waflib/extras/c_dumbpreproc.py0000664000000000000000000000272312145745420016230 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Dumb C/C++ preprocessor for finding dependencies It will look at all include files it can find after removing the comments, so the following will always add the dependency on both "a.h" and "b.h":: #include "a.h" #ifdef B #include "b.h" #endif int main() { return 0; } To use:: def configure(conf): conf.load('compiler_c') conf.load('c_dumbpreproc') """ import re, sys, os, string, traceback from waflib import Logs, Build, Utils, Errors from waflib.Logs import debug, error from waflib.Tools import c_preproc re_inc = re.compile( '^[ \t]*(#|%:)[ \t]*(include)[ \t]*[<"](.*)[>"]\r*$', re.IGNORECASE | re.MULTILINE) def lines_includes(node): code = node.read() if c_preproc.use_trigraphs: for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] parser = c_preproc.c_parser class dumb_parser(parser): def addlines(self, node): if node in self.nodes[:-1]: return self.currentnode_stack.append(node.parent) self.lines = lines_includes(node) + [(c_preproc.POPFILE, '')] + self.lines def start(self, node, env): self.addlines(node) while self.lines: (x, y) = self.lines.pop(0) if x == c_preproc.POPFILE: self.currentnode_stack.pop() continue self.tryfind(y) c_preproc.c_parser = dumb_parser debian/waf-1.7/waflib/extras/pgicxx.py0000664000000000000000000000067412145745420014711 0ustar #!/usr/bin/env python # encoding: utf-8 # Antoine Dechaume 2011 """ Detect the PGI C++ compiler """ import sys, re from waflib.Configure import conf from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['linux'].append('pgicxx') from waflib.extras import pgicc def configure(conf): conf.find_pgi_compiler('CXX', 'pgCC') conf.find_ar() conf.gxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/extras/valadoc.py0000664000000000000000000000765312145745420015024 0ustar #! /usr/bin/env python # encoding: UTF-8 # Nicolas Joseph 2009 """ ported from waf 1.5: TODO: tabs vs spaces """ from waflib import Task, Utils, Node, Errors, Logs from waflib.TaskGen import feature, extension, after_method VALADOC_STR = '${VALADOC}' class valadoc(Task.Task): vars = ['VALADOC', 'VALADOCFLAGS'] color = 'BLUE' after = ['cprogram', 'cstlib', 'cshlib', 'cxxprogram', 'cxxstlib', 'cxxshlib'] quiet = True # no outputs .. this is weird def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.output_dir = '' self.doclet = '' self.package_name = '' self.package_version = '' self.files = [] self.vapi_dirs = [] self.protected = True self.private = False self.inherit = False self.deps = False self.enable_non_null_experimental = False self.force = False def run(self): if not self.env['VALADOCFLAGS']: self.env['VALADOCFLAGS'] = '' cmd = [Utils.subst_vars(VALADOC_STR, self.env)] cmd.append ('-o %s' % self.output_dir) if getattr(self, 'doclet', None): cmd.append ('--doclet %s' % self.doclet) cmd.append ('--package-name %s' % self.package_name) if getattr(self, 'package_version', None): cmd.append ('--package-version %s' % self.package_version) if getattr(self, 'packages', None): for package in self.packages: cmd.append ('--pkg %s' % package) if getattr(self, 'vapi_dirs', None): for vapi_dir in self.vapi_dirs: cmd.append ('--vapidir %s' % vapi_dir) if not getattr(self, 'protected', None): cmd.append ('--no-protected') if getattr(self, 'private', None): cmd.append ('--private') if getattr(self, 'inherit', None): cmd.append ('--inherit') if getattr(self, 'deps', None): cmd.append ('--deps') if getattr(self, 'enable_non_null_experimental', None): cmd.append ('--enable-non-null-experimental') if getattr(self, 'force', None): cmd.append ('--force') cmd.append (' '.join ([x.abspath() for x in self.files])) return self.generator.bld.exec_command(' '.join(cmd)) @feature('valadoc') def process_valadoc(self): """ Generate API documentation from Vala source code with valadoc doc = bld( features = 'valadoc', output_dir = '../doc/html', package_name = 'vala-gtk-example', package_version = '1.0.0', packages = 'gtk+-2.0', vapi_dirs = '../vapi', force = True ) path = bld.path.find_dir ('../src') doc.files = path.ant_glob (incl='**/*.vala') """ task = self.create_task('valadoc') if getattr(self, 'output_dir', None): task.output_dir = self.path.find_or_declare(self.output_dir).abspath() else: Errors.WafError('no output directory') if getattr(self, 'doclet', None): task.doclet = self.doclet else: Errors.WafError('no doclet directory') if getattr(self, 'package_name', None): task.package_name = self.package_name else: Errors.WafError('no package name') if getattr(self, 'package_version', None): task.package_version = self.package_version if getattr(self, 'packages', None): task.packages = Utils.to_list(self.packages) if getattr(self, 'vapi_dirs', None): vapi_dirs = Utils.to_list(self.vapi_dirs) for vapi_dir in vapi_dirs: try: task.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath()) except AttributeError: Logs.warn("Unable to locate Vala API directory: '%s'" % vapi_dir) if getattr(self, 'files', None): task.files = self.files else: Errors.WafError('no input file') if getattr(self, 'protected', None): task.protected = self.protected if getattr(self, 'private', None): task.private = self.private if getattr(self, 'inherit', None): task.inherit = self.inherit if getattr(self, 'deps', None): task.deps = self.deps if getattr(self, 'enable_non_null_experimental', None): task.enable_non_null_experimental = self.enable_non_null_experimental if getattr(self, 'force', None): task.force = self.force def configure(conf): conf.find_program('valadoc', errmsg='You must install valadoc for generate the API documentation') debian/waf-1.7/waflib/extras/resx.py0000664000000000000000000000173412145745420014366 0ustar #! /usr/bin/env python # import os from waflib import Task from waflib.TaskGen import extension def configure(conf): conf.find_program(['resgen'], var='RESGEN') conf.env.RESGENFLAGS = '/useSourcePath' @extension('.resx') def resx_file(self, node): """ Bind the .resx extension to a resgen task """ if not getattr(self, 'cs_task', None): self.bld.fatal('resx_file has no link task for use %r' % self) # Given assembly 'Foo' and file 'Sub/Dir/File.resx', create 'Foo.Sub.Dir.File.resources' assembly = os.path.splitext(self.gen)[0] res = os.path.splitext(node.path_from(self.path))[0].replace('/', '.') out = self.path.find_or_declare(assembly + '.' + res + '.resources') tsk = self.create_task('resgen', node, out) self.cs_task.dep_nodes.extend(tsk.outputs) # dependency self.env.append_value('RESOURCES', tsk.outputs[0].bldpath()) class resgen(Task.Task): """ Compile C# resource files """ color = 'YELLOW' run_str = '${RESGEN} ${RESGENFLAGS} ${SRC} ${TGT}' debian/waf-1.7/waflib/extras/run_m_script.py0000664000000000000000000000604612145745420016112 0ustar #!/usr/bin/env python # encoding: utf-8 # Hans-Martin von Gaudecker, 2012 """ Run a Matlab script. Note that the script is run in the directory where it lives -- Matlab won't allow it any other way. For error-catching purposes, keep an own log-file that is destroyed if the task finished without error. If not, it will show up as mscript_[index].log in the bldnode directory. Usage:: ctx(features='run_m_script', source='some_script.m', target=['some_table.tex', 'some_figure.eps'], deps='some_data.mat') """ import os, sys from waflib import Task, TaskGen, Logs MATLAB_COMMANDS = ['matlab'] def configure(ctx): ctx.find_program(MATLAB_COMMANDS, var='MATLABCMD', errmsg = """\n No Matlab executable found!\n\n If Matlab is needed:\n 1) Check the settings of your system path. 2) Note we are looking for Matlab executables called: %s If yours has a different name, please report to hmgaudecker [at] gmail\n Else:\n Do not load the 'run_m_script' tool in the main wscript.\n\n""" % MATLAB_COMMANDS) ctx.env.MATLABFLAGS = '-wait -nojvm -nosplash -minimize' @Task.update_outputs class run_m_script_base(Task.Task): """Run a Matlab script.""" run_str = '"${MATLABCMD}" ${MATLABFLAGS} -logfile "${LOGFILEPATH}" -r "try, ${MSCRIPTTRUNK}, exit(0), catch err, disp(err.getReport()), exit(1), end"' shell = True class run_m_script(run_m_script_base): """Erase the Matlab overall log file if everything went okay, else raise an error and print its 10 last lines. """ def run(self): ret = run_m_script_base.run(self) logfile = self.env.LOGFILEPATH if ret: mode = 'r' if sys.version_info.major >= 3: mode = 'rb' with open(logfile, mode=mode) as f: tail = f.readlines()[-10:] Logs.error("""Running Matlab on %s returned the error %r\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""" % ( self.inputs[0].nice_path(), ret, logfile, '\n'.join(tail))) else: os.remove(logfile) return ret @TaskGen.feature('run_m_script') @TaskGen.before_method('process_source') def apply_run_m_script(tg): """Task generator customising the options etc. to call Matlab in batch mode for running a m-script. """ # Convert sources and targets to nodes src_node = tg.path.find_resource(tg.source) tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] tsk = tg.create_task('run_m_script', src=src_node, tgt=tgt_nodes) tsk.cwd = src_node.parent.abspath() tsk.env.MSCRIPTTRUNK = os.path.splitext(src_node.name)[0] tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s_%d.log' % (tsk.env.MSCRIPTTRUNK, tg.idx)) # dependencies (if the attribute 'deps' changes, trigger a recompilation) for x in tg.to_list(getattr(tg, 'deps', [])): node = tg.path.find_resource(x) if not node: tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.nice_path())) tsk.dep_nodes.append(node) Logs.debug('deps: found dependencies %r for running %r' % (tsk.dep_nodes, src_node.nice_path())) # Bypass the execution of process_source by setting the source to an empty list tg.source = [] debian/waf-1.7/waflib/extras/ocaml.py0000664000000000000000000002242512145745420014500 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) "ocaml support" import os, re from waflib import TaskGen, Utils, Task, Build from waflib.Logs import error from waflib.TaskGen import feature, before_method, after_method, extension EXT_MLL = ['.mll'] EXT_MLY = ['.mly'] EXT_MLI = ['.mli'] EXT_MLC = ['.c'] EXT_ML = ['.ml'] open_re = re.compile('^\s*open\s+([a-zA-Z]+)(;;){0,1}$', re.M) foo = re.compile(r"""(\(\*)|(\*\))|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^()*"'\\]*)""", re.M) def filter_comments(txt): meh = [0] def repl(m): if m.group(1): meh[0] += 1 elif m.group(2): meh[0] -= 1 elif not meh[0]: return m.group(0) return '' return foo.sub(repl, txt) def scan(self): node = self.inputs[0] code = filter_comments(node.read()) global open_re names = [] import_iterator = open_re.finditer(code) if import_iterator: for import_match in import_iterator: names.append(import_match.group(1)) found_lst = [] raw_lst = [] for name in names: nd = None for x in self.incpaths: nd = x.find_resource(name.lower()+'.ml') if not nd: nd = x.find_resource(name+'.ml') if nd: found_lst.append(nd) break else: raw_lst.append(name) return (found_lst, raw_lst) native_lst=['native', 'all', 'c_object'] bytecode_lst=['bytecode', 'all'] @feature('ocaml') def init_ml(self): Utils.def_attrs(self, type = 'all', incpaths_lst = [], bld_incpaths_lst = [], mlltasks = [], mlytasks = [], mlitasks = [], native_tasks = [], bytecode_tasks = [], linktasks = [], bytecode_env = None, native_env = None, compiled_tasks = [], includes = '', uselib = '', are_deps_set = 0) @feature('ocaml') @after_method('init_ml') def init_envs_ml(self): self.islibrary = getattr(self, 'islibrary', False) global native_lst, bytecode_lst self.native_env = None if self.type in native_lst: self.native_env = self.env.derive() if self.islibrary: self.native_env['OCALINKFLAGS'] = '-a' self.bytecode_env = None if self.type in bytecode_lst: self.bytecode_env = self.env.derive() if self.islibrary: self.bytecode_env['OCALINKFLAGS'] = '-a' if self.type == 'c_object': self.native_env.append_unique('OCALINKFLAGS_OPT', '-output-obj') @feature('ocaml') @before_method('apply_vars_ml') @after_method('init_envs_ml') def apply_incpaths_ml(self): inc_lst = self.includes.split() lst = self.incpaths_lst for dir in inc_lst: node = self.path.find_dir(dir) if not node: error("node not found: " + str(dir)) continue if not node in lst: lst.append(node) self.bld_incpaths_lst.append(node) # now the nodes are added to self.incpaths_lst @feature('ocaml') @before_method('process_source') def apply_vars_ml(self): for i in self.incpaths_lst: if self.bytecode_env: app = self.bytecode_env.append_value app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) if self.native_env: app = self.native_env.append_value app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) varnames = ['INCLUDES', 'OCAMLFLAGS', 'OCALINKFLAGS', 'OCALINKFLAGS_OPT'] for name in self.uselib.split(): for vname in varnames: cnt = self.env[vname+'_'+name] if cnt: if self.bytecode_env: self.bytecode_env.append_value(vname, cnt) if self.native_env: self.native_env.append_value(vname, cnt) @feature('ocaml') @after_method('process_source') def apply_link_ml(self): if self.bytecode_env: ext = self.islibrary and '.cma' or '.run' linktask = self.create_task('ocalink') linktask.bytecode = 1 linktask.set_outputs(self.path.find_or_declare(self.target + ext)) linktask.env = self.bytecode_env self.linktasks.append(linktask) if self.native_env: if self.type == 'c_object': ext = '.o' elif self.islibrary: ext = '.cmxa' else: ext = '' linktask = self.create_task('ocalinkx') linktask.set_outputs(self.path.find_or_declare(self.target + ext)) linktask.env = self.native_env self.linktasks.append(linktask) # we produce a .o file to be used by gcc self.compiled_tasks.append(linktask) @extension(*EXT_MLL) def mll_hook(self, node): mll_task = self.create_task('ocamllex', node, node.change_ext('.ml')) mll_task.env = self.native_env.derive() self.mlltasks.append(mll_task) self.source.append(mll_task.outputs[0]) @extension(*EXT_MLY) def mly_hook(self, node): mly_task = self.create_task('ocamlyacc', node, [node.change_ext('.ml'), node.change_ext('.mli')]) mly_task.env = self.native_env.derive() self.mlytasks.append(mly_task) self.source.append(mly_task.outputs[0]) task = self.create_task('ocamlcmi', mly_task.outputs[1], mly_task.outputs[1].change_ext('.cmi')) task.env = self.native_env.derive() @extension(*EXT_MLI) def mli_hook(self, node): task = self.create_task('ocamlcmi', node, node.change_ext('.cmi')) task.env = self.native_env.derive() self.mlitasks.append(task) @extension(*EXT_MLC) def mlc_hook(self, node): task = self.create_task('ocamlcc', node, node.change_ext('.o')) task.env = self.native_env.derive() self.compiled_tasks.append(task) @extension(*EXT_ML) def ml_hook(self, node): if self.native_env: task = self.create_task('ocamlx', node, node.change_ext('.cmx')) task.env = self.native_env.derive() task.incpaths = self.bld_incpaths_lst self.native_tasks.append(task) if self.bytecode_env: task = self.create_task('ocaml', node, node.change_ext('.cmo')) task.env = self.bytecode_env.derive() task.bytecode = 1 task.incpaths = self.bld_incpaths_lst self.bytecode_tasks.append(task) def compile_may_start(self): if not getattr(self, 'flag_deps', ''): self.flag_deps = 1 # the evil part is that we can only compute the dependencies after the # source files can be read (this means actually producing the source files) if getattr(self, 'bytecode', ''): alltasks = self.generator.bytecode_tasks else: alltasks = self.generator.native_tasks self.signature() # ensure that files are scanned - unfortunately tree = self.generator.bld env = self.env for node in self.inputs: lst = tree.node_deps[self.uid()] for depnode in lst: for t in alltasks: if t == self: continue if depnode in t.inputs: self.set_run_after(t) # TODO necessary to get the signature right - for now delattr(self, 'cache_sig') self.signature() return Task.Task.runnable_status(self) class ocamlx(Task.Task): """native caml compilation""" color = 'GREEN' run_str = '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' scan = scan runnable_status = compile_may_start class ocaml(Task.Task): """bytecode caml compilation""" color = 'GREEN' run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' scan = scan runnable_status = compile_may_start class ocamlcmi(Task.Task): """interface generator (the .i files?)""" color = 'BLUE' run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLINCLUDES} -o ${TGT} -c ${SRC}' before = ['ocamlcc', 'ocaml', 'ocamlcc'] class ocamlcc(Task.Task): """ocaml to c interfaces""" color = 'GREEN' run_str = 'cd ${TGT[0].bld_dir()} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${OCAMLINCLUDES} -c ${SRC[0].abspath()}' class ocamllex(Task.Task): """lexical generator""" color = 'BLUE' run_str = '${OCAMLLEX} ${SRC} -o ${TGT}' before = ['ocamlcmi', 'ocaml', 'ocamlcc'] class ocamlyacc(Task.Task): """parser generator""" color = 'BLUE' run_str = '${OCAMLYACC} -b ${TGT[0].bld_base(env)} ${SRC}' before = ['ocamlcmi', 'ocaml', 'ocamlcc'] def link_may_start(self): if getattr(self, 'bytecode', 0): alltasks = self.generator.bytecode_tasks else: alltasks = self.generator.native_tasks for x in alltasks: if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'order', ''): # now reorder the inputs given the task dependencies # this part is difficult, we do not have a total order on the tasks # if the dependencies are wrong, this may not stop seen = [] pendant = []+alltasks while pendant: task = pendant.pop(0) if task in seen: continue for x in task.run_after: if not x in seen: pendant.append(task) break else: seen.append(task) self.inputs = [x.outputs[0] for x in seen] self.order = 1 return Task.Task.runnable_status(self) class ocalink(Task.Task): """bytecode caml link""" color = 'YELLOW' run_str = '${OCAMLC} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS} ${SRC}' runnable_status = link_may_start after = ['ocaml', 'ocamlcc'] class ocalinkx(Task.Task): """native caml link""" color = 'YELLOW' run_str = '${OCAMLOPT} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS_OPT} ${SRC}' runnable_status = link_may_start after = ['ocamlx', 'ocamlcc'] def configure(conf): opt = conf.find_program('ocamlopt', var='OCAMLOPT', mandatory=False) occ = conf.find_program('ocamlc', var='OCAMLC', mandatory=False) if (not opt) or (not occ): conf.fatal('The objective caml compiler was not found:\ninstall it or make it available in your PATH') v = conf.env v['OCAMLC'] = occ v['OCAMLOPT'] = opt v['OCAMLLEX'] = conf.find_program('ocamllex', var='OCAMLLEX', mandatory=False) v['OCAMLYACC'] = conf.find_program('ocamlyacc', var='OCAMLYACC', mandatory=False) v['OCAMLFLAGS'] = '' v['OCAMLLIB'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIBPATH_OCAML'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['INCLUDES_OCAML'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIB_OCAML'] = 'camlrun' debian/waf-1.7/waflib/extras/lru_cache.py0000664000000000000000000000457612145745420015341 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy 2011 import os, shutil, re from waflib import Options, Build, Logs """ Apply a least recently used policy to the Waf cache. For performance reasons, it is called after the build is complete. We assume that the the folders are written atomically Do export WAFCACHE=/tmp/foo_xyz where xyz represents the cache size in bytes If missing, the default cache size will be set to 10GB """ re_num = re.compile('[a-zA-Z_-]+(\d+)') CACHESIZE = 10*1024*1024*1024 # in bytes CLEANRATIO = 0.8 DIRSIZE = 4096 def compile(self): if Options.cache_global and not Options.options.nocache: try: os.makedirs(Options.cache_global) except: pass try: self.raw_compile() finally: if Options.cache_global and not Options.options.nocache: self.sweep() def sweep(self): global CACHESIZE CACHEDIR = Options.cache_global # get the cache max size from the WAFCACHE filename re_num = re.compile('[a-zA-Z_]+(\d+)') val = re_num.sub('\\1', os.path.basename(Options.cache_global)) try: CACHESIZE = int(val) except: pass # map folder names to timestamps flist = {} for x in os.listdir(CACHEDIR): j = os.path.join(CACHEDIR, x) if os.path.isdir(j) and len(x) == 64: # dir names are md5 hexdigests flist[x] = [os.stat(j).st_mtime, 0] for (x, v) in flist.items(): cnt = DIRSIZE # each entry takes 4kB d = os.path.join(CACHEDIR, x) for k in os.listdir(d): cnt += os.stat(os.path.join(d, k)).st_size flist[x][1] = cnt total = sum([x[1] for x in flist.values()]) Logs.debug('lru: Cache size is %r' % total) if total >= CACHESIZE: Logs.debug('lru: Trimming the cache since %r > %r' % (total, CACHESIZE)) # make a list to sort the folders by timestamp lst = [(p, v[0], v[1]) for (p, v) in flist.items()] lst.sort(key=lambda x: x[1]) # sort by timestamp lst.reverse() while total >= CACHESIZE * CLEANRATIO: (k, t, s) = lst.pop() p = os.path.join(CACHEDIR, k) v = p + '.del' try: os.rename(p, v) except: # someone already did it pass else: try: shutil.rmtree(v) except: # this should not happen, but who knows? Logs.warn('If you ever see this message, report it (%r)' % v) total -= s del flist[k] Logs.debug('lru: Total at the end %r' % total) Build.BuildContext.raw_compile = Build.BuildContext.compile Build.BuildContext.compile = compile Build.BuildContext.sweep = sweep debian/waf-1.7/waflib/extras/xcode.py0000664000000000000000000002031212145745420014500 0ustar #! /usr/bin/env python # encoding: utf-8 # XCode 3/XCode 4 generator for Waf # Nicolas Mercier 2011 """ Usage: def options(opt): opt.load('xcode') $ waf configure xcode """ # TODO: support iOS projects from waflib import Context, TaskGen, Build, Utils import os, sys, random, time HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' MAP_EXT = { '.h' : "sourcecode.c.h", '.hh': "sourcecode.cpp.h", '.inl': "sourcecode.cpp.h", '.hpp': "sourcecode.cpp.h", '.c': "sourcecode.c.c", '.m': "sourcecode.c.objc", '.mm': "sourcecode.cpp.objcpp", '.cc': "sourcecode.cpp.cpp", '.cpp': "sourcecode.cpp.cpp", '.C': "sourcecode.cpp.cpp", '.cxx': "sourcecode.cpp.cpp", '.c++': "sourcecode.cpp.cpp", '.l': "sourcecode.lex", # luthor '.ll': "sourcecode.lex", '.y': "sourcecode.yacc", '.yy': "sourcecode.yacc", '.plist': "text.plist.xml", ".nib": "wrapper.nib", ".xib": "text.xib", } part1 = 0 part2 = 10000 part3 = 0 id = 562000999 def newid(): global id id = id + 1 return "%04X%04X%04X%012d" % (0, 10000, 0, id) class XCodeNode: def __init__(self): self._id = newid() def tostring(self, value): if isinstance(value, dict): result = "{\n" for k,v in value.items(): result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) result = result + "\t\t}" return result elif isinstance(value, str): return "\"%s\"" % value elif isinstance(value, list): result = "(\n" for i in value: result = result + "\t\t\t%s,\n" % self.tostring(i) result = result + "\t\t)" return result elif isinstance(value, XCodeNode): return value._id else: return str(value) def write_recursive(self, value, file): if isinstance(value, dict): for k,v in value.items(): self.write_recursive(v, file) elif isinstance(value, list): for i in value: self.write_recursive(i, file) elif isinstance(value, XCodeNode): value.write(file) def write(self, file): for attribute,value in self.__dict__.items(): if attribute[0] != '_': self.write_recursive(value, file) w = file.write w("\t%s = {\n" % self._id) w("\t\tisa = %s;\n" % self.__class__.__name__) for attribute,value in self.__dict__.items(): if attribute[0] != '_': w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) w("\t};\n\n") # Configurations class XCBuildConfiguration(XCodeNode): def __init__(self, name, settings = {}, env=None): XCodeNode.__init__(self) self.baseConfigurationReference = "" self.buildSettings = settings self.name = name if env and env.ARCH: settings['ARCHS'] = " ".join(env.ARCH) class XCConfigurationList(XCodeNode): def __init__(self, settings): XCodeNode.__init__(self) self.buildConfigurations = settings self.defaultConfigurationIsVisible = 0 self.defaultConfigurationName = settings and settings[0].name or "" # Group/Files class PBXFileReference(XCodeNode): def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): XCodeNode.__init__(self) self.fileEncoding = 4 if not filetype: _, ext = os.path.splitext(name) filetype = MAP_EXT.get(ext, 'text') self.lastKnownFileType = filetype self.name = name self.path = path self.sourceTree = sourcetree class PBXGroup(XCodeNode): def __init__(self, name, sourcetree = ""): XCodeNode.__init__(self) self.children = [] self.name = name self.sourceTree = sourcetree def add(self, root, sources): folders = {} def folder(n): if n == root: return self try: return folders[n] except KeyError: f = PBXGroup(n.name) p = folder(n.parent) folders[n] = f p.children.append(f) return f for s in sources: f = folder(s.parent) source = PBXFileReference(s.name, s.abspath()) f.children.append(source) # Targets class PBXLegacyTarget(XCodeNode): def __init__(self, action, target=''): XCodeNode.__init__(self) self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) if not target: self.buildArgumentsString = "%s %s" % (sys.argv[0], action) else: self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) self.buildPhases = [] self.buildToolPath = sys.executable self.buildWorkingDirectory = "" self.dependencies = [] self.name = target or action self.productName = target or action self.passBuildSettingsInEnvironment = 0 class PBXShellScriptBuildPhase(XCodeNode): def __init__(self, action, target): XCodeNode.__init__(self) self.buildActionMask = 2147483647 self.files = [] self.inputPaths = [] self.outputPaths = [] self.runOnlyForDeploymentPostProcessing = 0 self.shellPath = "/bin/sh" self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) class PBXNativeTarget(XCodeNode): def __init__(self, action, target, node, env): XCodeNode.__init__(self) conf = XCBuildConfiguration('waf', {'PRODUCT_NAME':target, 'CONFIGURATION_BUILD_DIR':node.parent.abspath()}, env) self.buildConfigurationList = XCConfigurationList([conf]) self.buildPhases = [PBXShellScriptBuildPhase(action, target)] self.buildRules = [] self.dependencies = [] self.name = target self.productName = target self.productType = "com.apple.product-type.application" self.productReference = PBXFileReference(target, node.abspath(), 'wrapper.application', 'BUILT_PRODUCTS_DIR') # Root project object class PBXProject(XCodeNode): def __init__(self, name, version): XCodeNode.__init__(self) self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) self.compatibilityVersion = version[0] self.hasScannedForEncodings = 1; self.mainGroup = PBXGroup(name) self.projectRoot = "" self.projectDirPath = "" self.targets = [] self._objectVersion = version[1] self._output = PBXGroup('out') self.mainGroup.children.append(self._output) def write(self, file): w = file.write w("// !$*UTF8*$!\n") w("{\n") w("\tarchiveVersion = 1;\n") w("\tclasses = {\n") w("\t};\n") w("\tobjectVersion = %d;\n" % self._objectVersion) w("\tobjects = {\n\n") XCodeNode.write(self, file) w("\t};\n") w("\trootObject = %s;\n" % self._id) w("}\n") def add_task_gen(self, tg): if not getattr(tg, 'mac_app', False): self.targets.append(PBXLegacyTarget('build', tg.name)) else: target = PBXNativeTarget('build', tg.name, tg.link_task.outputs[0].change_ext('.app'), tg.env) self.targets.append(target) self._output.children.append(target.productReference) class xcode(Build.BuildContext): cmd = 'xcode' fun = 'build' def collect_source(self, tg): source_files = tg.to_nodes(getattr(tg, 'source', [])) plist_files = tg.to_nodes(getattr(tg, 'mac_plist', [])) resource_files = [tg.path.find_node(i) for i in Utils.to_list(getattr(tg, 'mac_resources', []))] include_dirs = Utils.to_list(getattr(tg, 'includes', [])) + Utils.to_list(getattr(tg, 'export_dirs', [])) include_files = [] for x in include_dirs: if not isinstance(x, str): include_files.append(x) continue d = tg.path.find_node(x) if d: lst = [y for y in d.ant_glob(HEADERS_GLOB, flat=False)] include_files.extend(lst) # remove duplicates source = list(set(source_files + plist_files + resource_files + include_files)) source.sort(key=lambda x: x.abspath()) return source def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) p = PBXProject(appname, ('Xcode 3.2', 46)) for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue tg.post() features = Utils.to_list(getattr(tg, 'features', '')) group = PBXGroup(tg.name) group.add(tg.path, self.collect_source(tg)) p.mainGroup.children.append(group) if 'cprogram' or 'cxxprogram' in features: p.add_task_gen(tg) # targets that don't produce the executable but that you might want to run p.targets.append(PBXLegacyTarget('configure')) p.targets.append(PBXLegacyTarget('dist')) p.targets.append(PBXLegacyTarget('install')) p.targets.append(PBXLegacyTarget('check')) node = self.srcnode.make_node('%s.xcodeproj' % appname) node.mkdir() node = node.make_node('project.pbxproj') p.write(open(node.abspath(), 'w')) debian/waf-1.7/waflib/extras/gob2.py0000664000000000000000000000047212145745420014234 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 from waflib import TaskGen TaskGen.declare_chain( name = 'gob2', rule = '${GOB2} -o ${TGT[0].bld_dir()} ${GOB2FLAGS} ${SRC}', ext_in = '.gob', ext_out = '.c' ) def configure(conf): conf.find_program('gob2', var='GOB2') conf.env['GOB2FLAGS'] = '' debian/waf-1.7/waflib/extras/__init__.py0000664000000000000000000000010712145745420015135 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.7/waflib/extras/slow_qt4.py0000664000000000000000000000527212145745420015162 0ustar #! /usr/bin/env python # Thomas Nagy, 2011 (ita) """ Create _moc.cpp files The builds are 30-40% faster when .moc files are included, you should NOT use this tool. If you really really want it: def configure(conf): conf.load('compiler_cxx qt4') conf.load('slow_qt4') See playground/slow_qt/wscript for a complete example. """ from waflib.TaskGen import extension from waflib import Task import waflib.Tools.qt4 import waflib.Tools.cxx @extension(*waflib.Tools.qt4.EXT_QT4) def cxx_hook(self, node): self.create_compiled_task('cxx_qt', node) class cxx_qt(waflib.Tools.cxx.cxx): def runnable_status(self): ret = waflib.Tools.cxx.cxx.runnable_status(self) if ret != Task.ASK_LATER and not getattr(self, 'moc_done', None): try: cache = self.generator.moc_cache except AttributeError: cache = self.generator.moc_cache = {} deps = self.generator.bld.node_deps[self.uid()] for x in [self.inputs[0]] + deps: if x.read().find('Q_OBJECT') > 0: # process "foo.h -> foo.moc" only if "foo.cpp" is in the sources for the current task generator # this code will work because it is in the main thread (runnable_status) if x.name.rfind('.') > -1: # a .h file... name = x.name[:x.name.rfind('.')] for tsk in self.generator.compiled_tasks: if tsk.inputs and tsk.inputs[0].name.startswith(name): break else: # no corresponding file, continue continue # the file foo.cpp could be compiled for a static and a shared library - hence the %number in the name cxx_node = x.parent.get_bld().make_node(x.name.replace('.', '_') + '_%d_moc.cpp' % self.generator.idx) if cxx_node in cache: continue cache[cxx_node] = self tsk = Task.classes['moc'](env=self.env, generator=self.generator) tsk.set_inputs(x) tsk.set_outputs(cxx_node) if x.name.endswith('.cpp'): # moc is trying to be too smart but it is too dumb: # why forcing the #include when Q_OBJECT is in the cpp file? gen = self.generator.bld.producer gen.outstanding.insert(0, tsk) gen.total += 1 self.set_run_after(tsk) else: cxxtsk = Task.classes['cxx'](env=self.env, generator=self.generator) cxxtsk.set_inputs(tsk.outputs) cxxtsk.set_outputs(cxx_node.change_ext('.o')) cxxtsk.set_run_after(tsk) try: self.more_tasks.extend([tsk, cxxtsk]) except AttributeError: self.more_tasks = [tsk, cxxtsk] try: link = self.generator.link_task except: pass else: link.set_run_after(cxxtsk) link.inputs.extend(cxxtsk.outputs) self.moc_done = True for t in self.run_after: if not t.hasrun: return Task.ASK_LATER return ret debian/waf-1.7/waflib/extras/dumbpreproc.py0000664000000000000000000000272312145745420015726 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Dumb C/C++ preprocessor for finding dependencies It will look at all include files it can find after removing the comments, so the following will always add the dependency on both "a.h" and "b.h":: #include "a.h" #ifdef B #include "b.h" #endif int main() { return 0; } To use:: def configure(conf): conf.load('compiler_c') conf.load('c_dumbpreproc') """ import re, sys, os, string, traceback from waflib import Logs, Build, Utils, Errors from waflib.Logs import debug, error from waflib.Tools import c_preproc re_inc = re.compile( '^[ \t]*(#|%:)[ \t]*(include)[ \t]*[<"](.*)[>"]\r*$', re.IGNORECASE | re.MULTILINE) def lines_includes(node): code = node.read() if c_preproc.use_trigraphs: for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] parser = c_preproc.c_parser class dumb_parser(parser): def addlines(self, node): if node in self.nodes[:-1]: return self.currentnode_stack.append(node.parent) self.lines = lines_includes(node) + [(c_preproc.POPFILE, '')] + self.lines def start(self, node, env): self.addlines(node) while self.lines: (x, y) = self.lines.pop(0) if x == c_preproc.POPFILE: self.currentnode_stack.pop() continue self.tryfind(y) c_preproc.c_parser = dumb_parser debian/waf-1.7/waflib/extras/run_do_script.py0000664000000000000000000001165312145745420016260 0ustar #!/usr/bin/env python # encoding: utf-8 # Hans-Martin von Gaudecker, 2012 """ Run a Stata do-script in the directory specified by **ctx.bldnode**. The first and only argument will be the name of the do-script (no extension), which can be accessed inside the do-script by the local macro `1'. Useful for keeping a log file. The tool uses the log file that is automatically kept by Stata only for error-catching purposes, it will be destroyed if the task finished without error. In case of an error in **some_script.do**, you can inspect it as **some_script.log** in the **ctx.bldnode** directory. Note that Stata will not return an error code if it exits abnormally -- catching errors relies on parsing the log file mentioned before. Should the parser behave incorrectly please send an email to hmgaudecker [at] gmail. **WARNING** The tool will not work if multiple do-scripts of the same name---but in different directories---are run at the same time! Avoid this situation. Usage:: ctx(features='run_do_script', source='some_script.do', target=['some_table.tex', 'some_figure.eps'], deps='some_data.csv') """ import os, re, sys from waflib import Task, TaskGen, Logs if sys.platform == 'darwin': STATA_COMMANDS = ['Stata64MP', 'StataMP', 'Stata64SE', 'StataSE', 'Stata64', 'Stata'] STATAFLAGS = '-e -q do' STATAENCODING = 'MacRoman' elif sys.platform.startswith('linux'): STATA_COMMANDS = ['stata-mp', 'stata-se', 'stata'] STATAFLAGS = '-b -q do' # Not sure whether this is correct... STATAENCODING = 'Latin-1' elif sys.platform.lower().startswith('win'): STATA_COMMANDS = ['StataMP-64', 'StataMP-ia', 'StataMP', 'StataSE-64', 'StataSE-ia', 'StataSE', 'Stata-64', 'Stata-ia', 'Stata.e', 'WMPSTATA', 'WSESTATA', 'WSTATA'] STATAFLAGS = '/e do' STATAENCODING = 'Latin-1' else: raise Exception("Unknown sys.platform: %s " % sys.platform) def configure(ctx): ctx.find_program(STATA_COMMANDS, var='STATACMD', errmsg="""\n No Stata executable found!\n\n If Stata is needed:\n 1) Check the settings of your system path. 2) Note we are looking for Stata executables called: %s If yours has a different name, please report to hmgaudecker [at] gmail\n Else:\n Do not load the 'run_do_script' tool in the main wscript.\n\n""" % STATA_COMMANDS) ctx.env.STATAFLAGS = STATAFLAGS ctx.env.STATAENCODING = STATAENCODING @Task.update_outputs class run_do_script_base(Task.Task): """Run a Stata do-script from the bldnode directory.""" run_str = '"${STATACMD}" ${STATAFLAGS} "${SRC[0].abspath()}" "${DOFILETRUNK}"' shell = True class run_do_script(run_do_script_base): """Use the log file automatically kept by Stata for error-catching. Erase it if the task finished without error. If not, it will show up as do_script.log in the bldnode directory. """ def run(self): run_do_script_base.run(self) ret, log_tail = self.check_erase_log_file() if ret: Logs.error("""Running Stata on %s failed with code %r.\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""" % ( self.inputs[0].nice_path(), ret, self.env.LOGFILEPATH, log_tail)) return ret def check_erase_log_file(self): """Parse Stata's default log file and erase it if everything okay. Parser is based on Brendan Halpin's shell script found here: http://teaching.sociology.ul.ie/bhalpin/wordpress/?p=122 """ if sys.version_info.major >= 3: kwargs = {'file': self.env.LOGFILEPATH, 'mode': 'r', 'encoding': self.env.STATAENCODING} else: kwargs = {'name': self.env.LOGFILEPATH, 'mode': 'r'} with open(**kwargs) as log: log_tail = log.readlines()[-10:] for line in log_tail: error_found = re.match("r\(([0-9]+)\)", line) if error_found: return error_found.group(1), ''.join(log_tail) else: pass # Only end up here if the parser did not identify an error. os.remove(self.env.LOGFILEPATH) return None, None @TaskGen.feature('run_do_script') @TaskGen.before_method('process_source') def apply_run_do_script(tg): """Task generator customising the options etc. to call Stata in batch mode for running a do-script. """ # Convert sources and targets to nodes src_node = tg.path.find_resource(tg.source) tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] tsk = tg.create_task('run_do_script', src=src_node, tgt=tgt_nodes) tsk.env.DOFILETRUNK = os.path.splitext(src_node.name)[0] tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s.log' % (tsk.env.DOFILETRUNK)) # dependencies (if the attribute 'deps' changes, trigger a recompilation) for x in tg.to_list(getattr(tg, 'deps', [])): node = tg.path.find_resource(x) if not node: tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.nice_path())) tsk.dep_nodes.append(node) Logs.debug('deps: found dependencies %r for running %r' % (tsk.dep_nodes, src_node.nice_path())) # Bypass the execution of process_source by setting the source to an empty list tg.source = [] debian/waf-1.7/waflib/extras/protoc.py0000664000000000000000000000240212145745420014704 0ustar #!/usr/bin/env python # encoding: utf-8 # Philipp Bender, 2012 # Matt Clarkson, 2012 from waflib.Task import Task from waflib.TaskGen import extension """ A simple tool to integrate protocol buffers into your build system. def configure(conf): conf.load('compiler_cxx cxx protoc') def build(bld): bld( features = 'cxx cxxprogram' source = 'main.cpp file1.proto proto/file2.proto', include = '. proto', target = 'executable') """ class protoc(Task): run_str = '${PROTOC} ${PROTOC_FLAGS} ${PROTOC_ST:INCPATHS} ${SRC[0].abspath()}' color = 'BLUE' ext_out = ['.h', 'pb.cc'] @extension('.proto') def process_protoc(self, node): cpp_node = node.change_ext('.pb.cc') hpp_node = node.change_ext('.pb.h') self.create_task('protoc', node, [cpp_node, hpp_node]) self.source.append(cpp_node) if 'cxx' in self.features and not self.env.PROTOC_FLAGS: self.env.PROTOC_FLAGS = '--cpp_out=.' use = getattr(self, 'use', '') if not 'PROTOBUF' in use: self.use = self.to_list(use) + ['PROTOBUF'] def configure(conf): conf.check_cfg(package="protobuf", uselib_store="PROTOBUF", args=['--cflags', '--libs']) conf.find_program('protoc', var='PROTOC') conf.env.PROTOC_ST = '-I%s' debian/waf-1.7/waflib/extras/md5_tstamp.py0000664000000000000000000000415412145745420015461 0ustar #! /usr/bin/env python # encoding: utf-8 """ This module assumes that only one build context is running at a given time, which is not the case if you want to execute configuration tests in parallel. Store some values on the buildcontext mapping file paths to stat values and md5 values (timestamp + md5) this way the md5 hashes are computed only when timestamp change (can be faster) There is usually little or no gain from enabling this, but it can be used to enable the second level cache with timestamps (WAFCACHE) You may have to run distclean or to remove the build directory before enabling/disabling this hashing scheme """ import os, stat try: import cPickle except: import pickle as cPickle from waflib import Utils, Build, Context STRONGEST = True try: Build.BuildContext.store_real except AttributeError: Context.DBFILE += '_md5tstamp' Build.hashes_md5_tstamp = {} Build.SAVED_ATTRS.append('hashes_md5_tstamp') def store(self): # save the hash cache as part of the default pickle file self.hashes_md5_tstamp = Build.hashes_md5_tstamp self.store_real() Build.BuildContext.store_real = Build.BuildContext.store Build.BuildContext.store = store def restore(self): # we need a module variable for h_file below self.restore_real() try: Build.hashes_md5_tstamp = self.hashes_md5_tstamp or {} except Exception as e: Build.hashes_md5_tstamp = {} Build.BuildContext.restore_real = Build.BuildContext.restore Build.BuildContext.restore = restore def h_file(filename): st = os.stat(filename) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') if filename in Build.hashes_md5_tstamp: if Build.hashes_md5_tstamp[filename][0] == str(st.st_mtime): return Build.hashes_md5_tstamp[filename][1] if STRONGEST: ret = Utils.h_file_no_md5(filename) Build.hashes_md5_tstamp[filename] = (str(st.st_mtime), ret) return ret else: m = Utils.md5() m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(filename) Build.hashes_md5_tstamp[filename] = (str(st.st_mtime), m.digest()) return m.digest() Utils.h_file_no_md5 = Utils.h_file Utils.h_file = h_file debian/waf-1.7/waflib/extras/review.py0000664000000000000000000002203312145745420014701 0ustar #!/usr/bin/env python # encoding: utf-8 # Laurent Birtz, 2011 # moved the code into a separate tool (ita) """ There are several things here: - a different command-line option management making options persistent - the review command to display the options set Assumptions: - configuration options are not always added to the right group (and do not count on the users to do it...) - the options are persistent between the executions (waf options are NOT persistent by design), even for the configuration - when the options change, the build is invalidated (forcing a reconfiguration) """ import os, textwrap, shutil from waflib import Logs, Context, ConfigSet, Options, Build, Configure class Odict(dict): """Ordered dictionary""" def __init__(self, data=None): self._keys = [] dict.__init__(self) if data: # we were provided a regular dict if isinstance(data, dict): self.append_from_dict(data) # we were provided a tuple list elif type(data) == list: self.append_from_plist(data) # we were provided invalid input else: raise Exception("expected a dict or a tuple list") def append_from_dict(self, dict): map(self.__setitem__, dict.keys(), dict.values()) def append_from_plist(self, plist): for pair in plist: if len(pair) != 2: raise Exception("invalid pairs list") for (k, v) in plist: self.__setitem__(k, v) def __delitem__(self, key): if not key in self._keys: raise KeyError(key) dict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): dict.__setitem__(self, key, item) if key not in self._keys: self._keys.append(key) def clear(self): dict.clear(self) self._keys = [] def copy(self): return Odict(self.plist()) def items(self): return zip(self._keys, self.values()) def keys(self): return list(self._keys) # return a copy of the list def values(self): return map(self.get, self._keys) def plist(self): p = [] for k, v in self.items(): p.append( (k, v) ) return p def __str__(self): s = "{" l = len(self._keys) for k, v in self.items(): l -= 1 strkey = str(k) if isinstance(k, basestring): strkey = "'"+strkey+"'" strval = str(v) if isinstance(v, basestring): strval = "'"+strval+"'" s += strkey + ":" + strval if l > 0: s += ", " s += "}" return s review_options = Odict() """ Ordered dictionary mapping configuration option names to their optparse option. """ review_defaults = {} """ Dictionary mapping configuration option names to their default value. """ old_review_set = None """ Review set containing the configuration values before parsing the command line. """ new_review_set = None """ Review set containing the configuration values after parsing the command line. """ class OptionsReview(Options.OptionsContext): def __init__(self, **kw): super(self.__class__, self).__init__(**kw) def prepare_config_review(self): """ Find the configuration options that are reviewable, detach their default value from their optparse object and store them into the review dictionaries. """ gr = self.get_option_group('configure options') for opt in gr.option_list: if opt.action != 'store' or opt.dest in ("out", "top"): continue review_options[opt.dest] = opt review_defaults[opt.dest] = opt.default if gr.defaults.has_key(opt.dest): del gr.defaults[opt.dest] opt.default = None def parse_args(self): self.prepare_config_review() self.parser.get_option('--prefix').help = 'installation prefix' super(OptionsReview, self).parse_args() Context.create_context('review').refresh_review_set() class ReviewContext(Context.Context): '''reviews the configuration values''' cmd = 'review' def __init__(self, **kw): super(self.__class__, self).__init__(**kw) out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf', '') self.build_path = (os.path.isabs(out) and self.root or self.path).make_node(out).abspath() """Path to the build directory""" self.cache_path = os.path.join(self.build_path, Build.CACHE_DIR) """Path to the cache directory""" self.review_path = os.path.join(self.cache_path, 'review.cache') """Path to the review cache file""" def execute(self): """ Display and store the review set. Invalidate the cache as required. """ if not self.compare_review_set(old_review_set, new_review_set): self.invalidate_cache() self.store_review_set(new_review_set) print(self.display_review_set(new_review_set)) def invalidate_cache(self): """Invalidate the cache to prevent bad builds.""" try: Logs.warn("Removing the cached configuration since the options have changed") shutil.rmtree(self.cache_path) except: pass def refresh_review_set(self): """ Obtain the old review set and the new review set, and import the new set. """ global old_review_set, new_review_set old_review_set = self.load_review_set() new_review_set = self.update_review_set(old_review_set) self.import_review_set(new_review_set) def load_review_set(self): """ Load and return the review set from the cache if it exists. Otherwise, return an empty set. """ if os.path.isfile(self.review_path): return ConfigSet.ConfigSet(self.review_path) return ConfigSet.ConfigSet() def store_review_set(self, review_set): """ Store the review set specified in the cache. """ if not os.path.isdir(self.cache_path): os.makedirs(self.cache_path) review_set.store(self.review_path) def update_review_set(self, old_set): """ Merge the options passed on the command line with those imported from the previous review set and return the corresponding preview set. """ # Convert value to string. It's important that 'None' maps to # the empty string. def val_to_str(val): if val == None or val == '': return '' return str(val) new_set = ConfigSet.ConfigSet() opt_dict = Options.options.__dict__ for name in review_options.keys(): # the option is specified explicitly on the command line if name in opt_dict: # if the option is the default, pretend it was never specified if val_to_str(opt_dict[name]) != val_to_str(review_defaults[name]): new_set[name] = opt_dict[name] # the option was explicitly specified in a previous command elif name in old_set: new_set[name] = old_set[name] return new_set def import_review_set(self, review_set): """ Import the actual value of the reviewable options in the option dictionary, given the current review set. """ for name in review_options.keys(): if name in review_set: value = review_set[name] else: value = review_defaults[name] setattr(Options.options, name, value) def compare_review_set(self, set1, set2): """ Return true if the review sets specified are equal. """ if len(set1.keys()) != len(set2.keys()): return False for key in set1.keys(): if not key in set2 or set1[key] != set2[key]: return False return True def display_review_set(self, review_set): """ Return the string representing the review set specified. """ term_width = Logs.get_term_cols() lines = [] for dest in review_options.keys(): opt = review_options[dest] name = ", ".join(opt._short_opts + opt._long_opts) help = opt.help actual = None if dest in review_set: actual = review_set[dest] default = review_defaults[dest] lines.append(self.format_option(name, help, actual, default, term_width)) return "Configuration:\n\n" + "\n\n".join(lines) + "\n" def format_option(self, name, help, actual, default, term_width): """ Return the string representing the option specified. """ def val_to_str(val): if val == None or val == '': return "(void)" return str(val) max_name_len = 20 sep_len = 2 w = textwrap.TextWrapper() w.width = term_width - 1 if w.width < 60: w.width = 60 out = "" # format the help out += w.fill(help) + "\n" # format the name name_len = len(name) out += Logs.colors.CYAN + name + Logs.colors.NORMAL # set the indentation used when the value wraps to the next line w.subsequent_indent = " ".rjust(max_name_len + sep_len) w.width -= (max_name_len + sep_len) # the name string is too long, switch to the next line if name_len > max_name_len: out += "\n" + w.subsequent_indent # fill the remaining of the line with spaces else: out += " ".rjust(max_name_len + sep_len - name_len) # format the actual value, if there is one if actual != None: out += Logs.colors.BOLD + w.fill(val_to_str(actual)) + Logs.colors.NORMAL + "\n" + w.subsequent_indent # format the default value default_fmt = val_to_str(default) if actual != None: default_fmt = "default: " + default_fmt out += Logs.colors.NORMAL + w.fill(default_fmt) + Logs.colors.NORMAL return out # Monkey-patch ConfigurationContext.execute() to have it store the review set. old_configure_execute = Configure.ConfigurationContext.execute def new_configure_execute(self): old_configure_execute(self) Context.create_context('review').store_review_set(new_review_set) Configure.ConfigurationContext.execute = new_configure_execute debian/waf-1.7/waflib/extras/biber.py0000664000000000000000000000313112145745420014461 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Latex processing using "biber" """ import os from waflib import Task, Logs from waflib.Tools import tex as texmodule class tex(texmodule.tex): biber_fun, _ = Task.compile_fun('${BIBER} ${BIBERFLAGS} ${SRCFILE}',shell=False) biber_fun.__doc__ = """ Execute the program **biber** """ def bibfile(self): return None def bibunits(self): self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS}) self.env.SRCFILE = self.aux_nodes[0].name[:-4] if not self.env['PROMPT_LATEX']: self.env.append_unique('BIBERFLAGS', '--quiet') path = self.aux_nodes[0].abspath()[:-4] + '.bcf' if os.path.isfile(path): Logs.warn('calling biber') self.check_status('error when calling biber, check %s.blg for errors' % (self.env.SRCFILE), self.biber_fun()) else: super(tex, self).bibfile() super(tex, self).bibunits() class latex(tex): texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) class pdflatex(tex): texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) class xelatex(tex): texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) def configure(self): """ Almost the same as in tex.py, but try to detect 'biber' """ v = self.env for p in ' biber tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): try: self.find_program(p, var=p.upper()) except self.errors.ConfigurationError: pass v['DVIPSFLAGS'] = '-Ppdf' debian/waf-1.7/waflib/extras/softlink_libs.py0000664000000000000000000000451112145745420016243 0ustar #! /usr/bin/env python # per rosengren 2011 from waflib.TaskGen import feature, after_method from waflib.Task import Task, always_run from os.path import basename, isabs from os import tmpfile, linesep def options(opt): grp = opt.add_option_group('Softlink Libraries Options') grp.add_option('--exclude', default='/usr/lib,/lib', help='No symbolic links are created for libs within [%default]') def configure(cnf): cnf.find_program('ldd') if not cnf.env.SOFTLINK_EXCLUDE: cnf.env.SOFTLINK_EXCLUDE = cnf.options.exclude.split(',') @feature('softlink_libs') @after_method('process_rule') def add_finder(self): tgt = self.path.find_or_declare(self.target) self.create_task('sll_finder', tgt=tgt) self.create_task('sll_installer', tgt=tgt) always_run(sll_installer) class sll_finder(Task): ext_out = 'softlink_libs' def run(self): bld = self.generator.bld linked=[] target_paths = [] for g in bld.groups: for tgen in g: # FIXME it might be better to check if there is a link_task (getattr?) target_paths += [tgen.path.get_bld().bldpath()] linked += [t.outputs[0].bldpath() for t in getattr(tgen, 'tasks', []) if t.__class__.__name__ in ['cprogram', 'cshlib', 'cxxprogram', 'cxxshlib']] lib_list = [] if len(linked): cmd = [self.env.LDD] + linked # FIXME add DYLD_LIBRARY_PATH+PATH for osx+win32 ldd_env = {'LD_LIBRARY_PATH': ':'.join(target_paths + self.env.LIBPATH)} # FIXME the with syntax will not work in python 2 with tmpfile() as result: self.exec_command(cmd, env=ldd_env, stdout=result) result.seek(0) for line in result.readlines(): words = line.split() if len(words) < 3 or words[1] != '=>': continue lib = words[2] if lib == 'not': continue if any([lib.startswith(p) for p in [bld.bldnode.abspath(), '('] + self.env.SOFTLINK_EXCLUDE]): continue if not isabs(lib): continue lib_list.append(lib) lib_list = sorted(set(lib_list)) self.outputs[0].write(linesep.join(lib_list + self.env.DYNAMIC_LIBS)) return 0 class sll_installer(Task): ext_in = 'softlink_libs' def run(self): tgt = self.outputs[0] self.generator.bld.install_files('${LIBDIR}', tgt, postpone=False) lib_list=tgt.read().split() for lib in lib_list: self.generator.bld.symlink_as('${LIBDIR}/'+basename(lib), lib, postpone=False) return 0 debian/waf-1.7/waflib/extras/cython.py0000664000000000000000000000726112145745420014712 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 import re import waflib import waflib.Logs as _msg from waflib import Task from waflib.TaskGen import extension, feature, before_method, after_method cy_api_pat = re.compile(r'\s*?cdef\s*?(public|api)\w*') re_cyt = re.compile(r""" (?:from\s+(\w+)\s+)? # optionally match "from foo" and capture foo c?import\s(\w+|[*]) # require "import bar" and capture bar """, re.M | re.VERBOSE) @extension('.pyx') def add_cython_file(self, node): """ Process a *.pyx* file given in the list of source files. No additional feature is required:: def build(bld): bld(features='c cshlib pyext', source='main.c foo.pyx', target='app') """ ext = '.c' if 'cxx' in self.features: self.env.append_unique('CYTHONFLAGS', '--cplus') ext = '.cc' for x in getattr(self, 'cython_includes', []): # TODO re-use these nodes in "scan" below d = self.path.find_dir(x) if d: self.env.append_unique('CYTHONFLAGS', '-I%s' % d.abspath()) tsk = self.create_task('cython', node, node.change_ext(ext)) self.source += tsk.outputs class cython(Task.Task): run_str = '${CYTHON} ${CYTHONFLAGS} -o ${TGT[0].abspath()} ${SRC}' color = 'GREEN' vars = ['INCLUDES'] """ Rebuild whenever the INCLUDES change. The variables such as CYTHONFLAGS will be appended by the metaclass. """ ext_out = ['.h'] """ The creation of a .h file is known only after the build has begun, so it is not possible to compute a build order just by looking at the task inputs/outputs. """ def runnable_status(self): """ Perform a double-check to add the headers created by cython to the output nodes. The scanner is executed only when the cython task must be executed (optimization). """ ret = super(cython, self).runnable_status() if ret == Task.ASK_LATER: return ret for x in self.generator.bld.raw_deps[self.uid()]: if x.startswith('header:'): self.outputs.append(self.inputs[0].parent.find_or_declare(x.replace('header:', ''))) return super(cython, self).runnable_status() def scan(self): """ Return the dependent files (.pxd) by looking in the include folders. Put the headers to generate in the custom list "bld.raw_deps". To inspect the scanne results use:: $ waf clean build --zones=deps """ txt = self.inputs[0].read() mods = [] for m in re_cyt.finditer(txt): if m.group(1): # matches "from foo import bar" mods.append(m.group(1)) else: mods.append(m.group(2)) _msg.debug("cython: mods %r" % mods) incs = getattr(self.generator, 'cython_includes', []) incs = [self.generator.path.find_dir(x) for x in incs] incs.append(self.inputs[0].parent) found = [] missing = [] for x in mods: for y in incs: k = y.find_resource(x + '.pxd') if k: found.append(k) break else: missing.append(x) _msg.debug("cython: found %r" % found) # Now the .h created - store them in bld.raw_deps for later use has_api = False has_public = False for l in txt.splitlines(): if cy_api_pat.match(l): if ' api ' in l: has_api = True if ' public ' in l: has_public = True name = self.inputs[0].name.replace('.pyx', '') if has_api: missing.append('header:%s_api.h' % name) if has_public: missing.append('header:%s.h' % name) return (found, missing) def options(ctx): ctx.add_option('--cython-flags', action='store', default='', help='space separated list of flags to pass to cython') def configure(ctx): if not ctx.env.CC and not ctx.env.CXX: ctx.fatal('Load a C/C++ compiler first') if not ctx.env.PYTHON: ctx.fatal('Load the python tool first!') ctx.find_program('cython', var='CYTHON') if ctx.options.cython_flags: ctx.env.CYTHONFLAGS = ctx.options.cython_flags debian/waf-1.7/waflib/extras/gccdeps.py0000664000000000000000000001231612145745420015013 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Execute the tasks with gcc -MD, read the dependencies from the .d file and prepare the dependency calculation for the next run """ import os, re, threading from waflib import Task, Logs, Utils, Errors from waflib.Tools import c_preproc from waflib.TaskGen import before_method, feature lock = threading.Lock() preprocessor_flag = '-MD' # Third-party tools are allowed to add extra names in here with append() supported_compilers = ['gcc', 'icc'] @feature('c') @before_method('process_source') def add_mmd_cc(self): if self.env.CC_NAME in supported_compilers and self.env.get_flat('CFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CFLAGS', [preprocessor_flag]) @feature('cxx') @before_method('process_source') def add_mmd_cxx(self): if self.env.CC_NAME in supported_compilers and self.env.get_flat('CXXFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CXXFLAGS', [preprocessor_flag]) def scan(self): "the scanner does not do anything initially" if self.env.CC_NAME not in supported_compilers: return self.no_gccdeps_scan() nodes = self.generator.bld.node_deps.get(self.uid(), []) names = [] return (nodes, names) re_o = re.compile("\.o$") re_splitter = re.compile(r'(?= 0: return line[sep_idx + 2:] else: return line def path_to_node(base_node, path, cached_nodes): # Take the base node and the path and return a node # Results are cached because searching the node tree is expensive # The following code is executed by threads, it is not safe, so a lock is needed... if getattr(path, '__hash__'): node_lookup_key = (base_node, path) else: # Not hashable, assume it is a list and join into a string node_lookup_key = (base_node, os.path.sep.join(path)) try: lock.acquire() node = cached_nodes[node_lookup_key] except KeyError: node = base_node.find_resource(path) cached_nodes[node_lookup_key] = node finally: lock.release() return node def post_run(self): # The following code is executed by threads, it is not safe, so a lock is needed... if self.env.CC_NAME not in supported_compilers: return self.no_gccdeps_post_run() if getattr(self, 'cached', None): return Task.Task.post_run(self) name = self.outputs[0].abspath() name = re_o.sub('.d', name) txt = Utils.readf(name) #os.unlink(name) # Compilers have the choice to either output the file's dependencies # as one large Makefile rule: # # /path/to/file.o: /path/to/dep1.h \ # /path/to/dep2.h \ # /path/to/dep3.h \ # ... # # or as many individual rules: # # /path/to/file.o: /path/to/dep1.h # /path/to/file.o: /path/to/dep2.h # /path/to/file.o: /path/to/dep3.h # ... # # So the first step is to sanitize the input by stripping out the left- # hand side of all these lines. After that, whatever remains are the # implicit dependencies of task.outputs[0] txt = '\n'.join([remove_makefile_rule_lhs(line) for line in txt.splitlines()]) # Now join all the lines together txt = txt.replace('\\\n', '') val = txt.strip() lst = val.split(':') val = [x.replace('\\ ', ' ') for x in re_splitter.split(val) if x] nodes = [] bld = self.generator.bld # Dynamically bind to the cache try: cached_nodes = bld.cached_nodes except AttributeError: cached_nodes = bld.cached_nodes = {} for x in val: node = None if os.path.isabs(x): node = path_to_node(bld.root, x, cached_nodes) else: path = bld.bldnode # when calling find_resource, make sure the path does not begin by '..' x = [k for k in Utils.split_path(x) if k and k != '.'] while lst and x[0] == '..': x = x[1:] path = path.parent node = path_to_node(path, x, cached_nodes) if not node: raise ValueError('could not find %r for %r' % (x, self)) else: if not c_preproc.go_absolute: if not (node.is_child_of(bld.srcnode) or node.is_child_of(bld.bldnode)): continue if id(node) == id(self.inputs[0]): # ignore the source file, it is already in the dependencies # this way, successful config tests may be retrieved from the cache continue nodes.append(node) Logs.debug('deps: real scanner for %s returned %s' % (str(self), str(nodes))) bld.node_deps[self.uid()] = nodes bld.raw_deps[self.uid()] = [] try: del self.cache_sig except: pass Task.Task.post_run(self) def sig_implicit_deps(self): if self.env.CC_NAME not in supported_compilers: return self.no_gccdeps_sig_implicit_deps() try: return Task.Task.sig_implicit_deps(self) except Errors.WafError: return Utils.SIG_NIL for name in 'c cxx'.split(): try: cls = Task.classes[name] except KeyError: pass else: cls.no_gccdeps_post_run = cls.post_run cls.no_gccdeps_scan = cls.scan cls.no_gccdeps_sig_implicit_deps = cls.sig_implicit_deps cls.post_run = post_run cls.scan = scan cls.sig_implicit_deps = sig_implicit_deps debian/waf-1.7/waflib/extras/scala.py0000664000000000000000000000661712145745420014475 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Scala support scalac outputs files a bit where it wants to """ import os, re from waflib.Configure import conf from waflib import TaskGen, Task, Utils, Options, Build, Errors, Node from waflib.TaskGen import feature, before_method, after_method from waflib.Tools import ccroot ccroot.USELIB_VARS['scalac'] = set(['CLASSPATH', 'SCALACFLAGS']) from waflib.Tools import javaw @feature('scalac') @before_method('process_source') def apply_scalac(self): Utils.def_attrs(self, jarname='', classpath='', sourcepath='.', srcdir='.', jar_mf_attributes={}, jar_mf_classpath=[]) nodes_lst = [] outdir = getattr(self, 'outdir', None) if outdir: if not isinstance(outdir, Node.Node): outdir = self.path.get_bld().make_node(self.outdir) else: outdir = self.path.get_bld() outdir.mkdir() self.env['OUTDIR'] = outdir.abspath() self.scalac_task = tsk = self.create_task('scalac') tmp = [] srcdir = getattr(self, 'srcdir', '') if isinstance(srcdir, Node.Node): srcdir = [srcdir] for x in Utils.to_list(srcdir): if isinstance(x, Node.Node): y = x else: y = self.path.find_dir(x) if not y: self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) tmp.append(y) tsk.srcdir = tmp # reuse some code feature('scalac')(javaw.use_javac_files) after_method('apply_scalac')(javaw.use_javac_files) feature('scalac')(javaw.set_classpath) after_method('apply_scalac', 'use_scalac_files')(javaw.set_classpath) SOURCE_RE = '**/*.scala' class scalac(javaw.javac): color = 'GREEN' vars = ['CLASSPATH', 'SCALACFLAGS', 'SCALAC', 'OUTDIR'] def runnable_status(self): """ Wait for dependent tasks to be complete, then read the file system to find the input nodes. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global SOURCE_RE self.inputs = [] for x in self.srcdir: self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) return super(javaw.javac, self).runnable_status() def run(self): """ Execute the scalac compiler """ env = self.env gen = self.generator bld = gen.bld wd = bld.bldnode.abspath() def to_list(xx): if isinstance(xx, str): return [xx] return xx self.last_cmd = lst = [] lst.extend(to_list(env['SCALAC'])) lst.extend(['-classpath']) lst.extend(to_list(env['CLASSPATH'])) lst.extend(['-d']) lst.extend(to_list(env['OUTDIR'])) lst.extend(to_list(env['SCALACFLAGS'])) lst.extend([a.abspath() for a in self.inputs]) lst = [x for x in lst if x] try: self.out = self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, output=0, quiet=0)[1] except: self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None) def configure(self): """ Detect the scalac program """ # If SCALA_HOME is set, we prepend it to the path list java_path = self.environ['PATH'].split(os.pathsep) v = self.env if 'SCALA_HOME' in self.environ: java_path = [os.path.join(self.environ['SCALA_HOME'], 'bin')] + java_path self.env['SCALA_HOME'] = [self.environ['SCALA_HOME']] for x in 'scalac scala'.split(): self.find_program(x, var=x.upper(), path_list=java_path) self.env[x.upper()] = self.cmd_to_list(self.env[x.upper()]) if 'CLASSPATH' in self.environ: v['CLASSPATH'] = self.environ['CLASSPATH'] v.SCALACFLAGS = ['-verbose'] if not v['SCALAC']: self.fatal('scalac is required for compiling scala classes') debian/waf-1.7/waflib/extras/run_r_script.py0000664000000000000000000000537412145745420016122 0ustar #!/usr/bin/env python # encoding: utf-8 # Hans-Martin von Gaudecker, 2012 """ Run a R script in the directory specified by **ctx.bldnode**. For error-catching purposes, keep an own log-file that is destroyed if the task finished without error. If not, it will show up as rscript_[index].log in the bldnode directory. Usage:: ctx(features='run_r_script', source='some_script.r', target=['some_table.tex', 'some_figure.eps'], deps='some_data.csv') """ import os, sys from waflib import Task, TaskGen, Logs R_COMMANDS = ['RTerm', 'R', 'r'] def configure(ctx): ctx.find_program(R_COMMANDS, var='RCMD', errmsg = """\n No R executable found!\n\n If R is needed:\n 1) Check the settings of your system path. 2) Note we are looking for R executables called: %s If yours has a different name, please report to hmgaudecker [at] gmail\n Else:\n Do not load the 'run_r_script' tool in the main wscript.\n\n""" % R_COMMANDS) ctx.env.RFLAGS = 'CMD BATCH --slave' @Task.update_outputs class run_r_script_base(Task.Task): """Run a R script.""" run_str = '"${RCMD}" ${RFLAGS} "${SRC[0].abspath()}" "${LOGFILEPATH}"' shell = True class run_r_script(run_r_script_base): """Erase the R overall log file if everything went okay, else raise an error and print its 10 last lines. """ def run(self): ret = run_r_script_base.run(self) logfile = self.env.LOGFILEPATH if ret: mode = 'r' if sys.version_info.major >= 3: mode = 'rb' with open(logfile, mode=mode) as f: tail = f.readlines()[-10:] Logs.error("""Running R on %s returned the error %r\n\nCheck the log file %s, last 10 lines\n\n%s\n\n\n""" % ( self.inputs[0].nice_path(), ret, logfile, '\n'.join(tail))) else: os.remove(logfile) return ret @TaskGen.feature('run_r_script') @TaskGen.before_method('process_source') def apply_run_r_script(tg): """Task generator customising the options etc. to call R in batch mode for running a R script. """ # Convert sources and targets to nodes src_node = tg.path.find_resource(tg.source) tgt_nodes = [tg.path.find_or_declare(t) for t in tg.to_list(tg.target)] tsk = tg.create_task('run_r_script', src=src_node, tgt=tgt_nodes) tsk.env.LOGFILEPATH = os.path.join(tg.bld.bldnode.abspath(), '%s_%d.log' % (os.path.splitext(src_node.name)[0], tg.idx)) # dependencies (if the attribute 'deps' changes, trigger a recompilation) for x in tg.to_list(getattr(tg, 'deps', [])): node = tg.path.find_resource(x) if not node: tg.bld.fatal('Could not find dependency %r for running %r' % (x, src_node.nice_path())) tsk.dep_nodes.append(node) Logs.debug('deps: found dependencies %r for running %r' % (tsk.dep_nodes, src_node.nice_path())) # Bypass the execution of process_source by setting the source to an empty list tg.source = [] debian/waf-1.7/waflib/extras/dpapi.py0000664000000000000000000000557212145745420014506 0ustar #! /usr/bin/env python # encoding: utf-8 # Matt Clarkson, 2012 ''' DPAPI access library (http://msdn.microsoft.com/en-us/library/ms995355.aspx) This file uses code originally created by Crusher Joe: http://article.gmane.org/gmane.comp.python.ctypes/420 And modified by Wayne Koorts: http://stackoverflow.com/questions/463832/using-dpapi-with-python ''' from ctypes import windll, byref, cdll, Structure, POINTER, c_char, c_buffer from ctypes.wintypes import DWORD from waflib.Configure import conf LocalFree = windll.kernel32.LocalFree memcpy = cdll.msvcrt.memcpy CryptProtectData = windll.crypt32.CryptProtectData CryptUnprotectData = windll.crypt32.CryptUnprotectData CRYPTPROTECT_UI_FORBIDDEN = 0x01 try: extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd'.encode('ascii') except AttributeError: extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd' class DATA_BLOB(Structure): _fields_ = [ ('cbData', DWORD), ('pbData', POINTER(c_char)) ] def get_data(blob_out): cbData = int(blob_out.cbData) pbData = blob_out.pbData buffer = c_buffer(cbData) memcpy(buffer, pbData, cbData) LocalFree(pbData); return buffer.raw @conf def dpapi_encrypt_data(self, input_bytes, entropy = extra_entropy): ''' Encrypts data and returns byte string :param input_bytes: The data to be encrypted :type input_bytes: String or Bytes :param entropy: Extra entropy to add to the encryption process (optional) :type entropy: String or Bytes ''' if not isinstance(input_bytes, bytes) or not isinstance(entropy, bytes): self.fatal('The inputs to dpapi must be bytes') buffer_in = c_buffer(input_bytes, len(input_bytes)) buffer_entropy = c_buffer(entropy, len(entropy)) blob_in = DATA_BLOB(len(input_bytes), buffer_in) blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) blob_out = DATA_BLOB() if CryptProtectData(byref(blob_in), 'python_data', byref(blob_entropy), None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): return get_data(blob_out) else: self.fatal('Failed to decrypt data') @conf def dpapi_decrypt_data(self, encrypted_bytes, entropy = extra_entropy): ''' Decrypts data and returns byte string :param encrypted_bytes: The encrypted data :type encrypted_bytes: Bytes :param entropy: Extra entropy to add to the encryption process (optional) :type entropy: String or Bytes ''' if not isinstance(encrypted_bytes, bytes) or not isinstance(entropy, bytes): self.fatal('The inputs to dpapi must be bytes') buffer_in = c_buffer(encrypted_bytes, len(encrypted_bytes)) buffer_entropy = c_buffer(entropy, len(entropy)) blob_in = DATA_BLOB(len(encrypted_bytes), buffer_in) blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) blob_out = DATA_BLOB() if CryptUnprotectData(byref(blob_in), None, byref(blob_entropy), None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): return get_data(blob_out) else: self.fatal('Failed to decrypt data') debian/waf-1.7/waflib/extras/print_commands.py0000664000000000000000000000205012145745420016412 0ustar #! /usr/bin/env python """ Illustrate how to override a class method to do something In this case, print the commands being executed as strings (the commands are usually lists, so this can be misleading) """ import sys from waflib import Context, Utils, Logs def exec_command(self, cmd, **kw): subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) txt = cmd if isinstance(cmd, list): txt = ' '.join(cmd) print(txt) Logs.debug('runner_env: kw=%s' % kw) try: if self.logger: # warning: may deadlock with a lot of output (subprocess limitation) self.logger.info(cmd) kw['stdout'] = kw['stderr'] = subprocess.PIPE p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() if out: self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) if err: self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) return p.returncode else: p = subprocess.Popen(cmd, **kw) return p.wait() except OSError: return -1 Context.Context.exec_command = exec_command debian/waf-1.7/waflib/extras/ticgt.py0000664000000000000000000002303212145745420014512 0ustar #!/usr/bin/env python # encoding: utf-8 # Texas Instruments code generator support (experimental) # When reporting issues, please directly assign the bug to the maintainer. __author__ = __maintainer__ = "Jérôme Carretero " __copyright__ = "Jérôme Carretero, 2012" """ TI cgt6x is a compiler suite for TI DSPs. The toolchain does pretty weird things, and I'm sure I'm missing some of them. But still, the tool saves time. What this tool does is: - create a TI compiler environment - create TI compiler features, to handle some specifics about this compiler It has a few idiosyncracies, such as not giving the liberty of the .o file names - automatically activate them when using the TI compiler - handle the tconf tool The tool TODO: - the set_platform_flags() function is not nice - more tests - broaden tool scope, if needed """ import os, re from waflib import Configure, Options, Utils, Task, TaskGen from waflib.Tools import c, ccroot, c_preproc from waflib.Configure import conf from waflib.TaskGen import feature, before_method, taskgen_method from waflib.Tools.ccroot import link_task, stlink_task from waflib.Tools.c import cprogram opj = os.path.join @conf def find_ticc(conf): cc = conf.find_program(['cl6x'], var='CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) cc = conf.cmd_to_list(cc) conf.env.CC_NAME = 'ticc' conf.env.CC = cc @conf def find_tild(conf): ld = conf.find_program(['lnk6x'], var='LINK_CC', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) ld = conf.cmd_to_list(ld) conf.env.LINK_CC_NAME = 'tild' conf.env.LINK_CC = ld @conf def find_tiar(conf): ar = conf.find_program(['ar6x'], var='AR', path_list=opj(getattr(Options.options, 'ti-cgt-dir', ""), 'bin')) ar = conf.cmd_to_list(ar) conf.env.AR = ar conf.env.AR_NAME = 'tiar' conf.env.ARFLAGS = 'qru' @conf def ticc_common_flags(conf): v = conf.env if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-d%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-i%s' # template for adding libpaths v['STLIB_ST'] = '-l=%s.lib' v['STLIBPATH_ST'] = '-i%s' # program v['cprogram_PATTERN'] = '%s.out' # static lib #v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] v['cstlib_PATTERN'] = '%s.lib' def configure(conf): v = conf.env v.TI_CGT_DIR = getattr(Options.options, 'ti-cgt-dir', "") v.TI_DSPLINK_DIR = getattr(Options.options, 'ti-dsplink-dir', "") v.TI_BIOSUTILS_DIR = getattr(Options.options, 'ti-biosutils-dir', "") v.TI_DSPBIOS_DIR = getattr(Options.options, 'ti-dspbios-dir', "") v.TI_XDCTOOLS_DIR = getattr(Options.options, 'ti-xdctools-dir', "") conf.find_ticc() conf.find_tiar() conf.find_tild() conf.ticc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() v.TCONF = conf.cmd_to_list(conf.find_program(['tconf'], var='TCONF', path_list=v.TI_XDCTOOLS_DIR)) conf.env.TCONF_INCLUDES += [ opj(conf.env.TI_DSPBIOS_DIR, 'packages'), ] conf.env.INCLUDES += [ opj(conf.env.TI_CGT_DIR, 'include'), ] conf.env.LIBPATH += [ opj(conf.env.TI_CGT_DIR, "lib"), ] conf.env.INCLUDES_DSPBIOS += [ opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'include'), ] conf.env.LIBPATH_DSPBIOS += [ opj(conf.env.TI_DSPBIOS_DIR, 'packages', 'ti', 'bios', 'lib'), ] conf.env.INCLUDES_DSPLINK += [ opj(conf.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc'), ] @conf def ti_set_debug(cfg, debug=1): """ Sets debug flags for the compiler. TODO: - for each TI CFLAG/INCLUDES/LINKFLAGS/LIBPATH replace RELEASE by DEBUG - -g --no_compress """ if debug: cfg.env.CFLAGS += "-d_DEBUG -dDEBUG -dDDSP_DEBUG".split() @conf def ti_dsplink_set_platform_flags(cfg, splat, dsp, dspbios_ver, board): """ Sets the INCLUDES, LINKFLAGS for DSPLINK and TCONF_INCLUDES For the specific hardware. Assumes that DSPLINK was built in its own folder. :param splat: short platform name (eg. OMAPL138) :param dsp: DSP name (eg. 674X) :param dspbios_ver: string identifying DspBios version (eg. 5.XX) :param board: board name (eg. OMAPL138GEM) """ d1 = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver) d = opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', 'DspBios', dspbios_ver, board) cfg.env.TCONF_INCLUDES += [d1, d] cfg.env.INCLUDES_DSPLINK += [ opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'inc', dsp), d, ] cfg.env.LINKFLAGS_DSPLINK += [ opj(cfg.env.TI_DSPLINK_DIR, 'dsplink', 'dsp', 'export', 'BIN', 'DspBios', splat, board+'_0', 'RELEASE', 'dsplink%s.lib' % x) for x in ['', 'pool', 'mpcs', 'mplist', 'msg', 'data', 'notify', 'ringio'] ] def options(opt): opt.add_option('--with-ti-cgt', type='string', dest='ti-cgt-dir', help = 'Specify alternate cgt root folder', default="") opt.add_option('--with-ti-biosutils', type='string', dest='ti-biosutils-dir', help = 'Specify alternate biosutils folder', default="") opt.add_option('--with-ti-dspbios', type='string', dest='ti-dspbios-dir', help = 'Specify alternate dspbios folder', default="") opt.add_option('--with-ti-dsplink', type='string', dest='ti-dsplink-dir', help = 'Specify alternate dsplink folder', default="") opt.add_option('--with-ti-xdctools', type='string', dest='ti-xdctools-dir', help = 'Specify alternate xdctools folder', default="") class ti_cprogram(cprogram): """ Link object files into a c program Changes: - the linked executable to have a relative path (because we can) - put the LIBPATH first """ run_str = '${LINK_CC} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].bldpath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ' @feature("c") @before_method('apply_link') def use_ti_cprogram(self): """ Automatically uses ti_cprogram link process """ if 'cprogram' in self.features and self.env.CC_NAME == 'ticc': self.features.insert(0, "ti_cprogram") class ti_c(Task.Task): """ Compile task for the TI codegen compiler This compiler does not allow specifying the output file name, only the output path. """ "Compile C files into object files" run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${SRC} -c ${OUT}' vars = ['CCDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan def create_compiled_task(self, name, node): """ Overrides ccroot.create_compiled_task to support ti_c """ out = '%s' % (node.change_ext('.obj').name) if self.env.CC_NAME == 'ticc': name = 'ti_c' task = self.create_task(name, node, node.parent.find_or_declare(out)) self.env.OUT = '-fr%s' % (node.parent.get_bld().abspath()) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task @TaskGen.extension('.c') def c_hook(self, node): "Bind the c file extension to the creation of a :py:class:`waflib.Tools.c.c` instance" if self.env.CC_NAME == 'ticc': return create_compiled_task(self, 'ti_c', node) else: return self.create_compiled_task('c', node) @feature("ti-tconf") @before_method('process_source') def apply_tconf(self): sources = [x.get_src() for x in self.to_nodes(self.source, path=self.path.get_src())] node = sources[0] assert(sources[0].name.endswith(".tcf")) if len(sources) > 1: assert(sources[1].name.endswith(".cmd")) target = getattr(self, 'target', self.source) target_node = node.get_bld().parent.find_or_declare(node.name) procid = "%d" % int(getattr(self, 'procid', 0)) importpaths = [] includes = Utils.to_list(getattr(self, 'includes', [])) for x in includes + self.env.TCONF_INCLUDES: if x == os.path.abspath(x): importpaths.append(x) else: relpath = self.path.find_node(x).path_from(target_node.parent) importpaths.append(relpath) task = self.create_task('ti_tconf', sources, target_node.change_ext('.cdb')) task.path = self.path task.includes = includes task.cwd = target_node.parent.abspath() task.env = self.env.derive() task.env["TCONFSRC"] = node.path_from(target_node.parent) task.env["TCONFINC"] = '-Dconfig.importPath=%s' % ";".join(importpaths) task.env['TCONFPROGNAME'] = '-Dconfig.programName=%s' % target task.env['PROCID'] = procid task.outputs = [ target_node.change_ext("cfg_c.c"), target_node.change_ext("cfg.s62"), target_node.change_ext("cfg.cmd"), ] s62task = create_compiled_task(self, 'ti_c', task.outputs[1]) ctask = create_compiled_task(self, 'ti_c', task.outputs[0]) ctask.env = self.env.derive() self.add_those_o_files(target_node.change_ext("cfg.cmd")) if len(sources) > 1: self.add_those_o_files(sources[1]) self.source = [] re_tconf_include = re.compile(r'(?Putils\.importFile)\("(?P.*)"\)',re.M) class ti_tconf(Task.Task): run_str = '${TCONF} ${TCONFINC} ${TCONFPROGNAME} ${TCONFSRC} ${PROCID}' color = 'PINK' def scan(self): includes = Utils.to_list(getattr(self, 'includes', [])) def deps(node): nodes, names = [], [] if node: code = Utils.readf(node.abspath()) for match in re_tconf_include.finditer(code): path = match.group('file') if path: for x in includes: filename = opj(x, path) fi = self.path.find_resource(filename) if fi: subnodes, subnames = deps(fi) nodes += subnodes names += subnames nodes.append(fi) names.append(path) break return nodes, names return deps(self.inputs[0]) debian/waf-1.7/waflib/extras/doxygen.py0000664000000000000000000001232512145745420015060 0ustar #! /usr/bin/env python # encoding: UTF-8 # Thomas Nagy 2008-2010 (ita) """ Doxygen support Variables passed to bld(): * doxyfile -- the Doxyfile to use ported from waf 1.5 (incomplete) """ from fnmatch import fnmatchcase import os, os.path, re, stat from waflib import Task, Utils, Node, Logs from waflib.TaskGen import feature DOXY_STR = '${DOXYGEN} - ' DOXY_FMTS = 'html latex man rft xml'.split() DOXY_FILE_PATTERNS = '*.' + ' *.'.join(''' c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx hpp h++ idl odl cs php php3 inc m mm py f90c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx '''.split()) re_rl = re.compile('\\\\\r*\n', re.MULTILINE) re_nl = re.compile('\r*\n', re.M) def parse_doxy(txt): tbl = {} txt = re_rl.sub('', txt) lines = re_nl.split(txt) for x in lines: x = x.strip() if not x or x.startswith('#') or x.find('=') < 0: continue if x.find('+=') >= 0: tmp = x.split('+=') key = tmp[0].strip() if key in tbl: tbl[key] += ' ' + '+='.join(tmp[1:]).strip() else: tbl[key] = '+='.join(tmp[1:]).strip() else: tmp = x.split('=') tbl[tmp[0].strip()] = '='.join(tmp[1:]).strip() return tbl class doxygen(Task.Task): vars = ['DOXYGEN', 'DOXYFLAGS'] color = 'BLUE' def runnable_status(self): ''' self.pars are populated in runnable_status - because this function is being run *before* both self.pars "consumers" - scan() and run() set output_dir (node) for the output ''' for x in self.run_after: if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'pars', None): txt = self.inputs[0].read() self.pars = parse_doxy(txt) if not self.pars.get('OUTPUT_DIRECTORY'): self.pars['OUTPUT_DIRECTORY'] = self.inputs[0].parent.get_bld().abspath() self.doxy_inputs = getattr(self, 'doxy_inputs', []) if not self.pars.get('INPUT'): self.doxy_inputs.append(self.inputs[0].parent) else: for i in self.pars.get('INPUT').split(): if os.path.isabs(i): node = self.generator.bld.root.find_node(i) else: node = self.generator.path.find_node(i) if not node: self.generator.bld.fatal('Could not find the doxygen input %r' % i) self.doxy_inputs.append(node) if not getattr(self, 'output_dir', None): bld = self.generator.bld # First try to find an absolute path, then find or declare a relative path self.output_dir = bld.root.find_dir(self.pars['OUTPUT_DIRECTORY']) if not self.output_dir: self.output_dir = bld.path.find_or_declare(self.pars['OUTPUT_DIRECTORY']) self.signature() return Task.Task.runnable_status(self) def scan(self): if self.pars.get('RECURSIVE') == 'YES': Logs.warn("Doxygen RECURSIVE dependencies are not supported") exclude_patterns = self.pars.get('EXCLUDE_PATTERNS', '').split() file_patterns = self.pars.get('FILE_PATTERNS', '').split() if not file_patterns: file_patterns = DOXY_FILE_PATTERNS nodes = [] names = [] for node in self.doxy_inputs: if os.path.isdir(node.abspath()): for m in node.ant_glob(file_patterns): nodes.append(m) else: nodes.append(node) return (nodes, names) def run(self): dct = self.pars.copy() # TODO will break if paths have spaces dct['INPUT'] = ' '.join([x.abspath() for x in self.doxy_inputs]) code = '\n'.join(['%s = %s' % (x, dct[x]) for x in self.pars]) code = code.encode() # for python 3 #fmt = DOXY_STR % (self.inputs[0].parent.abspath()) cmd = Utils.subst_vars(DOXY_STR, self.env) env = self.env.env or None proc = Utils.subprocess.Popen(cmd, shell=True, stdin=Utils.subprocess.PIPE, env=env, cwd=self.generator.bld.path.get_bld().abspath()) proc.communicate(code) return proc.returncode def post_run(self): nodes = self.output_dir.ant_glob('**/*', quiet=True) for x in nodes: x.sig = Utils.h_file(x.abspath()) self.outputs += nodes return Task.Task.post_run(self) class tar(Task.Task): "quick tar creation" run_str = '${TAR} ${TAROPTS} ${TGT} ${SRC}' color = 'RED' after = ['doxygen'] def runnable_status(self): for x in getattr(self, 'input_tasks', []): if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'tar_done_adding', None): # execute this only once self.tar_done_adding = True for x in getattr(self, 'input_tasks', []): self.set_inputs(x.outputs) if not self.inputs: return Task.SKIP_ME return Task.Task.runnable_status(self) def __str__(self): tgt_str = ' '.join([a.nice_path(self.env) for a in self.outputs]) return '%s: %s\n' % (self.__class__.__name__, tgt_str) @feature('doxygen') def process_doxy(self): if not getattr(self, 'doxyfile', None): self.generator.bld.fatal('no doxyfile??') node = self.doxyfile if not isinstance(node, Node.Node): node = self.path.find_resource(node) if not node: raise ValueError('doxygen file not found') # the task instance dsk = self.create_task('doxygen', node) if getattr(self, 'doxy_tar', None): tsk = self.create_task('tar') tsk.input_tasks = [dsk] tsk.set_outputs(self.path.find_or_declare(self.doxy_tar)) if self.doxy_tar.endswith('bz2'): tsk.env['TAROPTS'] = ['cjf'] elif self.doxy_tar.endswith('gz'): tsk.env['TAROPTS'] = ['czf'] else: tsk.env['TAROPTS'] = ['cf'] def configure(conf): conf.find_program('doxygen', var='DOXYGEN') conf.find_program('tar', var='TAR') debian/waf-1.7/waflib/extras/c_bgxlc.py0000664000000000000000000000130312145745420014776 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import os from waflib.Tools import ccroot,ar from waflib.Configure import conf from waflib.Tools import xlc # method xlc_common_flags from waflib.Tools.compiler_c import c_compiler c_compiler['linux'].insert(0, 'c_bgxlc') @conf def find_bgxlc(conf): cc = conf.find_program(['bgxlc_r','bgxlc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_xlc_version(cc) conf.env.CC = cc conf.env.CC_NAME = 'bgxlc' def configure(conf): conf.find_bgxlc() conf.find_ar() conf.xlc_common_flags() conf.env.LINKFLAGS_cshlib = ['-G','-Wl,-bexpfull'] conf.env.LINKFLAGS_cprogram = [] conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/extras/pgicc.py0000664000000000000000000000326312145745420014471 0ustar #!/usr/bin/env python # encoding: utf-8 # Antoine Dechaume 2011 """ Detect the PGI C compiler """ import sys, re from waflib.Configure import conf from waflib.Tools.compiler_c import c_compiler c_compiler['linux'].append('pgicc') @conf def find_pgi_compiler(conf, var, name): """ Find the program name, and execute it to ensure it really is itself. """ if sys.platform == 'cygwin': conf.fatal('The PGI compiler does not work on Cygwin') v = conf.env cc = None if v[var]: cc = v[var] elif var in conf.environ: cc = conf.environ[var] if not cc: cc = conf.find_program(name, var=var) if not cc: conf.fatal('PGI Compiler (%s) was not found' % name) cc = conf.cmd_to_list(cc) v[var + '_VERSION'] = conf.get_pgi_version(cc) v[var] = cc v[var + '_NAME'] = 'pgi' @conf def get_pgi_version(conf, cc): """Find the version of a pgi compiler.""" version_re = re.compile(r"The Portland Group", re.I).search cmd = cc + ['-V', '-E'] # Issue 1078, prevent wrappers from linking try: out, err = conf.cmd_and_log(cmd, output=0) except Exception: conf.fatal('Could not find pgi compiler %r' % cmd) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not verify PGI signature') cmd = cc + ['-help=variable'] try: out, err = conf.cmd_and_log(cmd, output=0) except Exception: conf.fatal('Could not find pgi compiler %r' % cmd) version = re.findall('^COMPVER\s*=(.*)', out, re.M) if len(version) != 1: conf.fatal('Could not determine the compiler version') return version[0] def configure(conf): conf.find_pgi_compiler('CC', 'pgcc') conf.find_ar() conf.gcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.7/waflib/extras/boo.py0000664000000000000000000000435012145745420014161 0ustar #! /usr/bin/env python # encoding: utf-8 # Yannick LM 2011 """ Support for the boo programming language, for example:: bld(features = "boo", # necessary feature source = "src.boo", # list of boo files gen = "world.dll", # target type = "library", # library/exe ("-target:xyz" flag) name = "world" # necessary if the target is referenced by 'use' ) """ from waflib import Task from waflib.Configure import conf from waflib.TaskGen import feature, after_method, before_method, extension @extension('.boo') def boo_hook(self, node): # Nothing here yet ... # TODO filter the non-boo source files in 'apply_booc' and remove this method pass @feature('boo') @before_method('process_source') def apply_booc(self): """Create a booc task """ src_nodes = self.to_nodes(self.source) out_node = self.path.find_or_declare(self.gen) self.boo_task = self.create_task('booc', src_nodes, [out_node]) # Set variables used by the 'booc' task self.boo_task.env.OUT = '-o:%s' % out_node.abspath() # type is "exe" by default type = getattr(self, "type", "exe") self.boo_task.env.BOO_TARGET_TYPE = "-target:%s" % type @feature('boo') @after_method('apply_boo') def use_boo(self): """" boo applications honor the **use** keyword:: """ dep_names = self.to_list(getattr(self, 'use', [])) for dep_name in dep_names: dep_task_gen = self.bld.get_tgen_by_name(dep_name) if not dep_task_gen: continue dep_task_gen.post() dep_task = getattr(dep_task_gen, 'boo_task', None) if not dep_task: # Try a cs task: dep_task = getattr(dep_task_gen, 'cs_task', None) if not dep_task: # Try a link task: dep_task = getattr(dep_task, 'link_task', None) if not dep_task: # Abort ... continue self.boo_task.set_run_after(dep_task) # order self.boo_task.dep_nodes.extend(dep_task.outputs) # dependency self.boo_task.env.append_value('BOO_FLAGS', '-reference:%s' % dep_task.outputs[0].abspath()) class booc(Task.Task): """Compiles .boo files """ color = 'YELLOW' run_str = '${BOOC} ${BOO_FLAGS} ${BOO_TARGET_TYPE} ${OUT} ${SRC}' @conf def check_booc(self): self.find_program('booc', 'BOOC') self.env.BOO_FLAGS = ['-nologo'] def configure(self): """Check that booc is available """ self.check_booc() debian/waf-1.7/waflib/extras/sas.py0000664000000000000000000000376412145745420014200 0ustar #!/usr/bin/env python # encoding: utf-8 # Mark Coggeshall, 2010 "SAS support" import os, re from waflib import Utils, Task, TaskGen, Runner, Build, Errors, Node, Logs from waflib.TaskGen import feature, before_method sas_fun, _ = Task.compile_fun('sas -sysin ${SRCFILE} -log ${LOGFILE} -print ${LSTFILE}', shell=False) class sas(Task.Task): vars = ['SAS', 'SASFLAGS'] def run(task): command = 'SAS' env = task.env bld = task.generator.bld fun = sas_fun node = task.inputs[0] logfilenode = node.change_ext('.log') lstfilenode = node.change_ext('.lst') # set the cwd task.cwd = task.inputs[0].parent.get_src().abspath() Logs.debug('runner: %s on %s' % (command, node.abspath)) SASINPUTS = node.parent.get_bld().abspath() + os.pathsep + node.parent.get_src().abspath() + os.pathsep task.env.env = {'SASINPUTS': SASINPUTS} task.env.SRCFILE = node.abspath() task.env.LOGFILE = logfilenode.abspath() task.env.LSTFILE = lstfilenode.abspath() ret = fun(task) if ret: Logs.error('Running %s on %r returned a non-zero exit' % (command, node)) Logs.error('SRCFILE = %r' % node) Logs.error('LOGFILE = %r' % logfilenode) Logs.error('LSTFILE = %r' % lstfilenode) return ret @feature('sas') @before_method('process_source') def apply_sas(self): if not getattr(self, 'type', None) in ['sas']: self.type = 'sas' self.env['logdir'] = getattr(self, 'logdir', 'log') self.env['lstdir'] = getattr(self, 'lstdir', 'lst') deps_lst = [] if getattr(self, 'deps', None): deps = self.to_list(self.deps) for filename in deps: n = self.path.find_resource(filename) if not n: n = self.bld.root.find_resource(filename) if not n: raise Errors.WafError('cannot find input file %s for processing' % filename) if not n in deps_lst: deps_lst.append(n) for node in self.to_nodes(self.source): if self.type == 'sas': task = self.create_task('sas', src=node) task.dep_nodes = deps_lst self.source = [] def configure(self): self.find_program('sas', var='SAS', mandatory=False) debian/waf-1.7/waflib/extras/misc.py0000664000000000000000000002662212145745420014343 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ This tool is totally deprecated Try using: .pc.in files for .pc files the feature intltool_in - see demos/intltool make-like rules """ import shutil, re, os from waflib import TaskGen, Node, Task, Utils, Build, Errors from waflib.TaskGen import feature, after_method, before_method from waflib.Logs import debug def copy_attrs(orig, dest, names, only_if_set=False): """ copy class attributes from an object to another """ for a in Utils.to_list(names): u = getattr(orig, a, ()) if u or not only_if_set: setattr(dest, a, u) def copy_func(tsk): "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)" env = tsk.env infile = tsk.inputs[0].abspath() outfile = tsk.outputs[0].abspath() try: shutil.copy2(infile, outfile) except (OSError, IOError): return 1 else: if tsk.chmod: os.chmod(outfile, tsk.chmod) return 0 def action_process_file_func(tsk): "Ask the function attached to the task to process it" if not tsk.fun: raise Errors.WafError('task must have a function attached to it for copy_func to work!') return tsk.fun(tsk) @feature('cmd') def apply_cmd(self): "call a command everytime" if not self.fun: raise Errors.WafError('cmdobj needs a function!') tsk = Task.TaskBase() tsk.fun = self.fun tsk.env = self.env self.tasks.append(tsk) tsk.install_path = self.install_path @feature('copy') @before_method('process_source') def apply_copy(self): Utils.def_attrs(self, fun=copy_func) self.default_install_path = 0 lst = self.to_list(self.source) self.meths.remove('process_source') for filename in lst: node = self.path.find_resource(filename) if not node: raise Errors.WafError('cannot find input file %s for processing' % filename) target = self.target if not target or len(lst)>1: target = node.name # TODO the file path may be incorrect newnode = self.path.find_or_declare(target) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.chmod = getattr(self, 'chmod', Utils.O644) if not tsk.env: tsk.debug() raise Errors.WafError('task without an environment') def subst_func(tsk): "Substitutes variables in a .in file" m4_re = re.compile('@(\w+)@', re.M) code = tsk.inputs[0].read() #Utils.readf(infile) # replace all % by %% to prevent errors by % signs in the input file while string formatting code = code.replace('%', '%%') s = m4_re.sub(r'%(\1)s', code) env = tsk.env di = getattr(tsk, 'dict', {}) or getattr(tsk.generator, 'dict', {}) if not di: names = m4_re.findall(code) for i in names: di[i] = env.get_flat(i) or env.get_flat(i.upper()) tsk.outputs[0].write(s % di) @feature('subst') @before_method('process_source') def apply_subst(self): Utils.def_attrs(self, fun=subst_func) lst = self.to_list(self.source) self.meths.remove('process_source') self.dict = getattr(self, 'dict', {}) for filename in lst: node = self.path.find_resource(filename) if not node: raise Errors.WafError('cannot find input file %s for processing' % filename) if self.target: newnode = self.path.find_or_declare(self.target) else: newnode = node.change_ext('') try: self.dict = self.dict.get_merged_dict() except AttributeError: pass if self.dict and not self.env['DICT_HASH']: self.env = self.env.derive() keys = list(self.dict.keys()) keys.sort() lst = [self.dict[x] for x in keys] self.env['DICT_HASH'] = str(Utils.h_list(lst)) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.dict = self.dict tsk.dep_vars = ['DICT_HASH'] tsk.chmod = getattr(self, 'chmod', Utils.O644) if not tsk.env: tsk.debug() raise Errors.WafError('task without an environment') #################### ## command-output #### #################### class cmd_arg(object): """command-output arguments for representing files or folders""" def __init__(self, name, template='%s'): self.name = name self.template = template self.node = None class input_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_resource(self.name) if self.node is None: raise Errors.WafError("Input file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath() else: return self.template % self.node.srcpath() class output_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_or_declare(self.name) if self.node is None: raise Errors.WafError("Output file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath() else: return self.template % self.node.bldpath() class cmd_dir_arg(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_dir(self.name) if self.node is None: raise Errors.WafError("Directory %s not found in " % (self.name, base_path)) class input_dir(cmd_dir_arg): def get_path(self, dummy_env, dummy_absolute): return self.template % self.node.abspath() class output_dir(cmd_dir_arg): def get_path(self, env, dummy_absolute): return self.template % self.node.abspath() class command_output(Task.Task): color = "BLUE" def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr): Task.Task.__init__(self, env=env) assert isinstance(command, (str, Node.Node)) self.command = command self.command_args = command_args self.stdin = stdin self.stdout = stdout self.cwd = cwd self.os_env = os_env self.stderr = stderr if command_node is not None: self.dep_nodes = [command_node] self.dep_vars = [] # additional environment variables to look def run(self): task = self #assert len(task.inputs) > 0 def input_path(node, template): if task.cwd is None: return template % node.bldpath() else: return template % node.abspath() def output_path(node, template): fun = node.abspath if task.cwd is None: fun = node.bldpath return template % fun() if isinstance(task.command, Node.Node): argv = [input_path(task.command, '%s')] else: argv = [task.command] for arg in task.command_args: if isinstance(arg, str): argv.append(arg) else: assert isinstance(arg, cmd_arg) argv.append(arg.get_path(task.env, (task.cwd is not None))) if task.stdin: stdin = open(input_path(task.stdin, '%s')) else: stdin = None if task.stdout: stdout = open(output_path(task.stdout, '%s'), "w") else: stdout = None if task.stderr: stderr = open(output_path(task.stderr, '%s'), "w") else: stderr = None if task.cwd is None: cwd = ('None (actually %r)' % os.getcwd()) else: cwd = repr(task.cwd) debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" % (cwd, stdin, stdout, argv)) if task.os_env is None: os_env = os.environ else: os_env = task.os_env command = Utils.subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env) return command.wait() @feature('command-output') def init_cmd_output(self): Utils.def_attrs(self, stdin = None, stdout = None, stderr = None, # the command to execute command = None, # whether it is an external command; otherwise it is assumed # to be an executable binary or script that lives in the # source or build tree. command_is_external = False, # extra parameters (argv) to pass to the command (excluding # the command itself) argv = [], # dependencies to other objects -> this is probably not what you want (ita) # values must be 'task_gen' instances (not names!) dependencies = [], # dependencies on env variable contents dep_vars = [], # input files that are implicit, i.e. they are not # stdin, nor are they mentioned explicitly in argv hidden_inputs = [], # output files that are implicit, i.e. they are not # stdout, nor are they mentioned explicitly in argv hidden_outputs = [], # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here) cwd = None, # OS environment variables to pass to the subprocess # if None, use the default environment variables unchanged os_env = None) @feature('command-output') @after_method('init_cmd_output') def apply_cmd_output(self): if self.command is None: raise Errors.WafError("command-output missing command") if self.command_is_external: cmd = self.command cmd_node = None else: cmd_node = self.path.find_resource(self.command) assert cmd_node is not None, ('''Could not find command '%s' in source tree. Hint: if this is an external command, use command_is_external=True''') % (self.command,) cmd = cmd_node if self.cwd is None: cwd = None args = [] inputs = [] outputs = [] for arg in self.argv: if isinstance(arg, cmd_arg): arg.find_node(self.path) if isinstance(arg, input_file): inputs.append(arg.node) if isinstance(arg, output_file): outputs.append(arg.node) if self.stdout is None: stdout = None else: assert isinstance(self.stdout, str) stdout = self.path.find_or_declare(self.stdout) if stdout is None: raise Errors.WafError("File %s not found" % (self.stdout,)) outputs.append(stdout) if self.stderr is None: stderr = None else: assert isinstance(self.stderr, str) stderr = self.path.find_or_declare(self.stderr) if stderr is None: raise Errors.WafError("File %s not found" % (self.stderr,)) outputs.append(stderr) if self.stdin is None: stdin = None else: assert isinstance(self.stdin, str) stdin = self.path.find_resource(self.stdin) if stdin is None: raise Errors.WafError("File %s not found" % (self.stdin,)) inputs.append(stdin) for hidden_input in self.to_list(self.hidden_inputs): node = self.path.find_resource(hidden_input) if node is None: raise Errors.WafError("File %s not found in dir %s" % (hidden_input, self.path)) inputs.append(node) for hidden_output in self.to_list(self.hidden_outputs): node = self.path.find_or_declare(hidden_output) if node is None: raise Errors.WafError("File %s not found in dir %s" % (hidden_output, self.path)) outputs.append(node) if not (inputs or getattr(self, 'no_inputs', None)): raise Errors.WafError('command-output objects must have at least one input file or give self.no_inputs') if not (outputs or getattr(self, 'no_outputs', None)): raise Errors.WafError('command-output objects must have at least one output file or give self.no_outputs') cwd = self.bld.variant_dir task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr) task.generator = self copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True) self.tasks.append(task) task.inputs = inputs task.outputs = outputs task.dep_vars = self.to_list(self.dep_vars) for dep in self.dependencies: assert dep is not self dep.post() for dep_task in dep.tasks: task.set_run_after(dep_task) if not task.inputs: # the case for svnversion, always run, and update the output nodes task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__) # TODO the case with no outputs? def post_run(self): for x in self.outputs: x.sig = Utils.h_file(x.abspath()) def runnable_status(self): return self.RUN_ME Task.task_factory('copy', vars=[], func=action_process_file_func) debian/waf-1.7/waflib/extras/batched_cc.py0000664000000000000000000001045412145745420015443 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Batched builds - compile faster instead of compiling object files one by one, c/c++ compilers are often able to compile at once: cc -c ../file1.c ../file2.c ../file3.c Files are output on the directory where the compiler is called, and dependencies are more difficult to track (do not run the command on all source files if only one file changes) As such, we do as if the files were compiled one by one, but no command is actually run: replace each cc/cpp Task by a TaskSlave. A new task called TaskMaster collects the signatures from each slave and finds out the command-line to run. It is only necessary to import this module in the configuration (no other change required) """ import os from waflib import TaskGen, Task, Build, Logs from waflib.TaskGen import extension, feature, before_method, after_method MAX_BATCH = 50 c_str = '${CC} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} -c ${SRCLST}' #c_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} -c ${SRCLST}' c_fun, _ = Task.compile_fun_noshell(c_str) cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} -c ${SRCLST}' #cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} -c ${SRCLST}' cxx_fun, _ = Task.compile_fun_noshell(cxx_str) count = 70000 class batch_task(Task.Task): color = 'RED' after = ['c', 'cxx'] before = ['cprogram', 'cshlib', 'cstlib', 'cxxprogram', 'cxxshlib', 'cxxstlib'] def __str__(self): return '(batch compilation for %d slaves)\n' % len(self.slaves) def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.slaves = [] self.inputs = [] self.hasrun = 0 global count count += 1 self.idx = count def add_slave(self, slave): self.slaves.append(slave) self.set_run_after(slave) def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for t in self.slaves: #if t.executed: if t.hasrun != Task.SKIPPED: return Task.RUN_ME return Task.SKIP_ME def run(self): outputs = [] self.outputs = [] srclst = [] slaves = [] for t in self.slaves: if t.hasrun != Task.SKIPPED: slaves.append(t) srclst.append(t.inputs[0].abspath()) self.env.SRCLST = srclst self.cwd = slaves[0].inputs[0].parent.get_bld().abspath() if self.slaves[0].__class__.__name__ == 'c': ret = c_fun(self) else: ret = cxx_fun(self) if ret: return ret for t in slaves: t.old_post_run() from waflib.Tools import c, cxx def hook(name): def n_hook(self, node): task = self.create_task(name, node, node.change_ext('.o')) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] if not getattr(self, 'masters', None): self.masters = {} self.allmasters = [] if not node.parent in self.masters: m = self.masters[node.parent] = self.master = self.create_task('batch') self.allmasters.append(m) else: m = self.masters[node.parent] if len(m.slaves) > MAX_BATCH: m = self.masters[node.parent] = self.master = self.create_task('batch') self.allmasters.append(m) m.add_slave(task) return task return n_hook extension('.c')(hook('c')) extension('.cpp','.cc','.cxx','.C','.c++')(hook('cxx')) @feature('cprogram', 'cshlib', 'cstaticlib', 'cxxprogram', 'cxxshlib', 'cxxstlib') @after_method('apply_link') def link_after_masters(self): if getattr(self, 'allmasters', None): for m in self.allmasters: self.link_task.set_run_after(m) # Modify the c and cxx task classes - in theory it would be better to # create subclasses and to re-map the c/c++ extensions # for x in ['c', 'cxx']: t = Task.classes[x] def run(self): pass def post_run(self): #self.executed=1 pass def can_retrieve_cache(self): if self.old_can_retrieve_cache(): for m in self.generator.allmasters: try: m.slaves.remove(self) except ValueError: pass #this task wasn't included in that master return 1 else: return None setattr(t, 'oldrun', t.__dict__['run']) setattr(t, 'run', run) setattr(t, 'old_post_run', t.post_run) setattr(t, 'post_run', post_run) setattr(t, 'old_can_retrieve_cache', t.can_retrieve_cache) setattr(t, 'can_retrieve_cache', can_retrieve_cache) debian/waf-1.7/waflib/extras/syms.py0000664000000000000000000000517112145745420014377 0ustar #! /usr/bin/env python # encoding: utf-8 """ this tool supports the export_symbols_regex to export the symbols in a shared library. by default, all symbols are exported by gcc, and nothing by msvc. to use the tool, do something like: def build(ctx): ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib') only the symbols starting with 'mylib_' will be exported. """ import re from waflib.Context import STDOUT from waflib.Task import Task from waflib.Errors import WafError from waflib.TaskGen import feature, after_method class gen_sym(Task): def run(self): obj = self.inputs[0] if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): re_nm = re.compile(r'External\s+\|\s+_(' + self.generator.export_symbols_regex + r')\b') cmd = ['dumpbin', '/symbols', obj.abspath()] else: if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows re_nm = re.compile(r'T\s+_(' + self.generator.export_symbols_regex + r')\b') else: re_nm = re.compile(r'T\s+(' + self.generator.export_symbols_regex + r')\b') cmd = ['nm', '-g', obj.abspath()] syms = re_nm.findall(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT)) self.outputs[0].write('%r' % syms) class compile_sym(Task): def run(self): syms = {} for x in self.inputs: slist = eval(x.read()) for s in slist: syms[s] = 1 lsyms = syms.keys() lsyms.sort() if self.env.DEST_BINFMT == 'pe': self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms)) elif self.env.DEST_BINFMT == 'elf': self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n") else: raise WafError('NotImplemented') @feature('syms') @after_method('process_source', 'process_use', 'apply_link', 'process_uselib_local') def do_the_symbol_stuff(self): ins = [x.outputs[0] for x in self.compiled_tasks] self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins] tsk = self.create_task('compile_sym', [x.outputs[0] for x in self.gen_sym_tasks], self.path.find_or_declare(getattr(self, 'sym_filename', self.target + '.def'))) self.link_task.set_run_after(tsk) self.link_task.dep_nodes = [tsk.outputs[0]] if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): self.link_task.env.append_value('LINKFLAGS', ['/def:' + tsk.outputs[0].bldpath()]) elif self.env.DEST_BINFMT == 'pe': #gcc on windows takes *.def as an additional input self.link_task.inputs.append(tsk.outputs[0]) elif self.env.DEST_BINFMT == 'elf': self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + tsk.outputs[0].bldpath()]) else: raise WafError('NotImplemented') debian/waf-1.7/waflib/extras/unity.py0000664000000000000000000000257512145745420014561 0ustar #! /usr/bin/env python # encoding: utf-8 """ Take a group of C++ files and compile them at once. def options(opt): opt.load('compiler_cxx unity') """ import re from waflib import Task, Options, Logs from waflib.Tools import ccroot, cxx, c_preproc from waflib.TaskGen import extension, taskgen_method MAX_BATCH = 20 def options(opt): global MAX_BATCH opt.add_option('--batchsize', action='store', dest='batchsize', type='int', default=MAX_BATCH, help='batch size (0 for no batch)') class unity(Task.Task): color = 'BLUE' scan = c_preproc.scan def run(self): lst = ['#include "%s"\n' % node.abspath() for node in self.inputs] txt = ''.join(lst) self.outputs[0].write(txt) @taskgen_method def batch_size(self): return Options.options.batchsize @extension('.cpp', '.cc', '.cxx', '.C', '.c++') def make_cxx_batch(self, node): cnt = self.batch_size() if cnt <= 1: tsk = self.create_compiled_task('cxx', node) return tsk try: self.cnt_cxx except AttributeError: self.cnt_cxx = 0 x = getattr(self, 'master_cxx', None) if not x or len(x.inputs) >= cnt: x = self.master_cxx = self.create_task('unity') cxxnode = node.parent.find_or_declare('union_%s_%d_%d.cxx' % (self.idx, self.cnt_cxx, cnt)) self.master_cxx.outputs = [cxxnode] self.cnt_cxx += 1 self.create_compiled_task('cxx', cxxnode) x.inputs.append(node) debian/waf-1.7/waflib/Logs.py0000664000000000000000000001560112145745420013001 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ logging, colors, terminal width and pretty-print """ import os, re, traceback, sys try: import threading except ImportError: pass else: wlock = threading.Lock() class sync_stream(object): def __init__(self, stream): self.stream = stream self.encoding = self.stream.encoding def write(self, txt): try: wlock.acquire() self.stream.write(txt) self.stream.flush() finally: wlock.release() def fileno(self): return self.stream.fileno() def flush(self): self.stream.flush() def isatty(self): return self.stream.isatty() _nocolor = os.environ.get('NOCOLOR', 'no') not in ('no', '0', 'false') try: if not _nocolor: import waflib.ansiterm except ImportError: pass if not os.environ.get('NOSYNC', False): if id(sys.stdout) == id(sys.__stdout__): sys.stdout = sync_stream(sys.stdout) sys.stderr = sync_stream(sys.stderr) import logging # import other modules only after LOG_FORMAT = "%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s" HOUR_FORMAT = "%H:%M:%S" zones = '' verbose = 0 colors_lst = { 'USE' : True, 'BOLD' :'\x1b[01;1m', 'RED' :'\x1b[01;31m', 'GREEN' :'\x1b[32m', 'YELLOW':'\x1b[33m', 'PINK' :'\x1b[35m', 'BLUE' :'\x1b[01;34m', 'CYAN' :'\x1b[36m', 'NORMAL':'\x1b[0m', 'cursor_on' :'\x1b[?25h', 'cursor_off' :'\x1b[?25l', } got_tty = not os.environ.get('TERM', 'dumb') in ['dumb', 'emacs'] if got_tty: try: got_tty = sys.stderr.isatty() and sys.stdout.isatty() except AttributeError: got_tty = False if (not got_tty and os.environ.get('TERM', 'dumb') != 'msys') or _nocolor: colors_lst['USE'] = False def get_term_cols(): return 80 # If console packages are available, replace the dummy function with a real # implementation try: import struct, fcntl, termios except ImportError: pass else: if got_tty: def get_term_cols_real(): """ Private use only. """ dummy_lines, cols = struct.unpack("HHHH", \ fcntl.ioctl(sys.stderr.fileno(),termios.TIOCGWINSZ , \ struct.pack("HHHH", 0, 0, 0, 0)))[:2] return cols # try the function once to see if it really works try: get_term_cols_real() except Exception: pass else: get_term_cols = get_term_cols_real get_term_cols.__doc__ = """ Get the console width in characters. :return: the number of characters per line :rtype: int """ def get_color(cl): if not colors_lst['USE']: return '' return colors_lst.get(cl, '') class color_dict(object): """attribute-based color access, eg: colors.PINK""" def __getattr__(self, a): return get_color(a) def __call__(self, a): return get_color(a) colors = color_dict() re_log = re.compile(r'(\w+): (.*)', re.M) class log_filter(logging.Filter): """ The waf logs are of the form 'name: message', and can be filtered by 'waf --zones=name'. For example, the following:: from waflib import Logs Logs.debug('test: here is a message') Will be displayed only when executing:: $ waf --zones=test """ def __init__(self, name=None): pass def filter(self, rec): """ filter a record, adding the colors automatically * error: red * warning: yellow :param rec: message to record """ rec.c1 = colors.PINK rec.c2 = colors.NORMAL rec.zone = rec.module if rec.levelno >= logging.INFO: if rec.levelno >= logging.ERROR: rec.c1 = colors.RED elif rec.levelno >= logging.WARNING: rec.c1 = colors.YELLOW else: rec.c1 = colors.GREEN return True m = re_log.match(rec.msg) if m: rec.zone = m.group(1) rec.msg = m.group(2) if zones: return getattr(rec, 'zone', '') in zones or '*' in zones elif not verbose > 2: return False return True class formatter(logging.Formatter): """Simple log formatter which handles colors""" def __init__(self): logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) def format(self, rec): """Messages in warning, error or info mode are displayed in color by default""" if rec.levelno >= logging.WARNING or rec.levelno == logging.INFO: try: msg = rec.msg.decode('utf-8') except Exception: msg = rec.msg return '%s%s%s' % (rec.c1, msg, rec.c2) return logging.Formatter.format(self, rec) log = None """global logger for Logs.debug, Logs.error, etc""" def debug(*k, **kw): """ Wrap logging.debug, the output is filtered for performance reasons """ if verbose: k = list(k) k[0] = k[0].replace('\n', ' ') global log log.debug(*k, **kw) def error(*k, **kw): """ Wrap logging.errors, display the origin of the message when '-vv' is set """ global log log.error(*k, **kw) if verbose > 2: st = traceback.extract_stack() if st: st = st[:-1] buf = [] for filename, lineno, name, line in st: buf.append(' File "%s", line %d, in %s' % (filename, lineno, name)) if line: buf.append(' %s' % line.strip()) if buf: log.error("\n".join(buf)) def warn(*k, **kw): """ Wrap logging.warn """ global log log.warn(*k, **kw) def info(*k, **kw): """ Wrap logging.info """ global log log.info(*k, **kw) def init_log(): """ Initialize the loggers globally """ global log log = logging.getLogger('waflib') log.handlers = [] log.filters = [] hdlr = logging.StreamHandler() hdlr.setFormatter(formatter()) log.addHandler(hdlr) log.addFilter(log_filter()) log.setLevel(logging.DEBUG) def make_logger(path, name): """ Create a simple logger, which is often used to redirect the context command output:: from waflib import Logs bld.logger = Logs.make_logger('test.log', 'build') bld.check(header_name='sadlib.h', features='cxx cprogram', mandatory=False) bld.logger = None :param path: file name to write the log output to :type path: string :param name: logger name (loggers are reused) :type name: string """ logger = logging.getLogger(name) hdlr = logging.FileHandler(path, 'w') formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.DEBUG) return logger def make_mem_logger(name, to_log, size=10000): """ Create a memory logger to avoid writing concurrently to the main logger """ from logging.handlers import MemoryHandler logger = logging.getLogger(name) hdlr = MemoryHandler(size, target=to_log) formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.memhandler = hdlr logger.setLevel(logging.DEBUG) return logger def pprint(col, str, label='', sep='\n'): """ Print messages in color immediately on stderr:: from waflib import Logs Logs.pprint('RED', 'Something bad just happened') :param col: color name to use in :py:const:`Logs.colors_lst` :type col: string :param str: message to display :type str: string or a value that can be printed by %s :param label: a message to add after the colored output :type label: string :param sep: a string to append at the end (line separator) :type sep: string """ sys.stderr.write("%s%s%s %s%s" % (colors(col), str, colors.NORMAL, label, sep)) debian/waf-1.7/TODO0000664000000000000000000000044312145745420010745 0ustar Waf 1.7.x --------- * fix the remaining bugs * provide more extensions Can be useful: def bld_command(*k): fun = k[0] name = fun.__name__ from waflib.Build import BuildContext class tmp(BuildContext): cmd = name fun = name return fun @bld_command def foo(ctx): print ctx.env debian/waf-1.7/ChangeLog0000664000000000000000000003577612145745420012050 0ustar NEW IN WAF 1.7.10 ----------------- * Enhancements in the LaTeX support #1248 * Codelite plugin by Christian Klein * Validate the versioned library number #1180 * New export_defines keyword for C/C++/Fortran libraries * Python config tests enhancements #1231 #1261 * Enable the distribution of non-python data files #1265 * Improved the boost configuration output #1266 * Exclude intltoolcache from waf dist # 1267 * Use Utils.readf/Utils.writef to prevent build cache loss on windows platforms NEW IN WAF 1.7.9 ---------------- * Improved the patch submitted in #1237 as it caused regressions * Reverted the patch submitted in #1212 as it caused regressions * Added a cache to waflib/extras/gccdeps.py #1244 * Unit test ut_exec was not obtained properly #1245 NEW IN WAF 1.7.8 ---------------- * Fixed a configuration issue in the visual studio compiler (regression #1239) NEW IN WAF 1.7.7 ---------------- * XLC and XLF detection fixes #1230 * Fixed the multiple gcc/msvc builds #1237 * Better gdc detection on Ubuntu #1222 * Relative symlinks in symlink_as #1234 * Various improvements in the doxygen tool #1232 #1233 * Fixed windows filehandle issues on Python #1235 * Visual Studio 2012 detection improvements * OSX soname installation fix NEW IN WAF 1.7.6 ---------------- * Better encapsulation of conf.check_cfg(uselib_store=...) defines #1212 * Support for python modules in fortran * Extension files of D binaries on Mac * Raise an error when a tex manually-provided dependency is not found #1209 * Enforce a stable name in bld(rule=..., name=undefined) to prevent rebuilds * Enhanced support for flex on win32 and msys #1207 #1211 * Fixed a regression on configuration tests running with -Werror/-Wall #1220 NEW IN WAF 1.7.5 ---------------- * Fixed the kde4 library detection on Fedora * New tool for protocol buffers (protoc.py) #1184 * Fixed a syntax error affecting Python < 2.6 NEW IN WAF 1.7.4 ---------------- * Fixed a regression in the Node,Task and Context classes NEW IN WAF 1.7.3 ----------------- * Fixed the LD_LIBRARY_PATH race condition in waf_unit_test #1200 * Library detection fixes in boost.py #1199 * Various waf_unit_test enhancements #1194 * Use the same function signature main(int, char**) in all configuration tests #1192 * Fixed the Clang version number detection #1191 * Let the feature 'includes' propagate INCLUDES and FRAMEWORKPATH variables * Fix for incorrect installation paths #1202 * Cabal script (haskell) NEW IN WAF 1.7.2 ---------------- * Install bld.subst() targets * New scanner for winrc processing #1186 NEW IN WAF 1.7.1 ---------------- * Updated the exclusion regexps for "waf dist" * Added an example in playground/nasm * Enabled compatibility with pkgconf * Response files for c# #1182 * Minor docstring updates #1188 * New tool for compiling .net resource files (waflib/extras/resx.py) #1183 * New tool for compiling .midl files (waflib/extras/midl.py) #1185 NEW IN WAF 1.7.0 ---------------- * The compat15 tool is disabled by default (the README file explains how to enable it) * Python >= 2.4 is now required * Python >= 2.6 is required for creating the Waf file in the source tree * Added Utils.writef (similar to Utils.readf) * Added Node.evict() to provide more control over invalid references * Do not raise exception on --help when running on python 2.4 * Node.search -> Node.search_node (consistent with make_node and find_node) * Errors are reported on configuration test failures with execute=True #1111 * Added header prefixing (autoconf-like) #1117 * Removed the warnings on "waf install" #1120 * Extended bld.subst() to perform simple copies to the build directory * Removed the default DLL_EXPORT define on gcc/g++ shared libraries * Calling ctx.root.ant_glob(abspath) will now return results #1135 * New case-insentive option for ant_glob #1148 * Ported demos/asm to 64-bit, forcing gcc over as * Updated the gccdeps tool #1162 * Improved the C# processing #1154, #1153 * Removed the empty flags from LIB/INCLUDE in the msvc configuration #1159 * Added an 'encoding' parameter to bld.subst() * Detect Visual Studio 2011 beta * Detect cython dependencies of the form "from module import x" #1044 * Use the cython includes in the dependency scanner #1166 * Improved the behaviour of Utils.readf/Utils.writef on Win32 * Made Task.__repr__ more robust #1174 * Fixed the gcc builds on hp-ux * Let gccdeps work with other compilers #1179 NEW IN WAF 1.6.11 ----------------- * Enable custom variables for the boost detection #1089 * Disable the config test execution when detecting boost #1090 * Process moc classes in .cpp files by default #1095 * Apply the chmod attribute to the versioned libraries (vnum) #1097 * Fixed the python detection on OSX #1098 * Changed the win32 color settings for Windows 7 #1099 * Set the default fortran linker for ifort to xiar #1104 NEW IN WAF 1.6.10 ----------------- * Fixed the 'remove' attribute propagation in ant_glob #1086 * Fixed the behavior of recurse(name=xyz) when looking in existing folders * Fixed a problem with include paths in the relocation tool #1078 * Improved the pgicc compiler detection #1080 * Fixed the behavior of 'waf options' #1076 * Process larger java projects #1074 * Remove the ':' from the drives when dealing with foreign files and folders on Win32 * Let the 'subst' feature process a chmod attribute * Added a hook for distutils variable query #1083 NEW IN WAF 1.6.9 ---------------- * Fixed the duplicate moc file creation in slow_qt4 #1047 * Fixed the Visual Studio 2008 projects creation #1033 * Added a workaround to avoid creating include folders not under the build directory #1049 * Added a default virtual folder structure for out-of-tree build files #1053 * Added a way to set variants containing /, for example linux/debug * Added a more intuitive behaviour for conf.setenv() #1062 * Fixed the multiple bibliography processing for tex #1040 * Windows CE detection improvements #1065 * Fixed the library installation on OSX * Fixed the Powerpc/IPhone platform detection * Added an Xcode project generator NEW IN WAF 1.6.8 ---------------- * Fixed a typo in Utils.py affecting Win32 platforms (copystat) #1029 * Fixed a minor bug in the Eclipse project generator * Fixed a typo that prevented Waf from running on Pypy-trunk * Make the xlc/xlc++ compiler detection more accurate by looking at the version number #1022 * Minor perl, python and ruby tool improvements * Better logs for the boost detection #1036 * Fixed a performance issue in Runner.py #1039 * Changed the position of the linker flags #1025 NEW IN WAF 1.6.7 ---------------- * Provide more diagnostic for invalid build groups #914 * Various enhancements to msvs.py * Read MSVC_VERSIONS and MSVC_TARGETS from the command-line * Minor cross-compiler detection fix on msvc.py * Fix the redirections with pipes (waf configure > log) * Do not display runnable_status exceptions when running with -k * Let -k stop at the first runnable_status error and -kk run even further * Merge the add_object extension in the main line (source='file.o') * Make update_outputs more robust with changes in the task definition #1017 * Qt4 detection on Win32 NEW IN WAF 1.6.6 ---------------- * Fix the performance regression related to #974 NEW IN WAF 1.6.5 ---------------- * More documentation * Re-enable the colors for msys * Add the .ui files for the qt4 translations * Fix the conf.check_large_file() test * Fix the conf.check_library() in C++ mode #955 * Improve the latex scanner to avoid depending on generated files #943 * Remove the @file processing from the winrc tasks * Fix the python detection using python-config * Add the missing default includes and defines to the moc command * Improve support for hierarchical go-lang packages #953 * Fix the gfortran verbose flag detection on Windows * Fix the support of fortran import libraries #950 * Added a fix for running with Python 2.4 on Windows #949 * Limited support for IronPython * Support for older Visual Studio versions (VC6) #952 * New waf.bat file #964 * New method ConfigSet.keys * New Visual Studio and Eclipse CTD project generators (waflib/extras) * New lru_cache tool for use with WAFCACHE (waflib/extras) NEW IN WAF 1.6.4 ---------------- * Fix the Python detection on win32 #883 * Optimize the Python file installation #892 * Force +x permissions on installed fortran programs #893 * Qt library detection fixes #895 * Ensure that unit tests are executed only after the symlinks are created * Fix the precedence constraints for classes ending in _task #896 * Support the install_path attribute with add_pcfile #913 * Make the goprograms executable when installed #928 * Allow non-python data files in the waf executable #927 * Enforce a build order based on the scanner results #777, #922 * Multiple msvc detection fixes #907 #910 #923 #924 #926 * Fix the -of flag append with dmd #917 * Boost detection fixes #920 * Support newer javac compilers #921 * Fix the execution on python 2.3 for: "waf update", msvc.py, fc.py * Improve the support for mac applications (demos/mac_app) * Better default regexps in "waf step" * New error check for tasks creating the same nodes or having the same identifiers (waf -v) * New variables conf.env.NO_LOCK_IN_TOP/OUT/RUN for special projects (top='..') * New example on avoiding rebuilds when moving a project (playground/relocate) * Improve go-lang support for cgo-packages (fixes #932) * Fix the progress bar on cmd and msys NEW IN WAF 1.6.3 ---------------- * Fixed the interaction of Fortran configuration tests and WAFCACHE #842 * Various documentation fixes * Set the PYTHONARCHDIR variable for installing python extensions * Fixed the Waf file creation with --zip-type=gz (bunzip2 was not replaced by gzip -d) * Fixed multiple problems in the call to TaskGen.declare_chain(...) #850 * Fixed the task attribute 'vars' which might cause unnecessary rebuilds #852 * Return the value of post_check(...) in conf.check(...) #857 * Rewrite the boost tool (waflib/extras/boost.py) #814, #454, #424 * More fortran file extensions: .for, .FOR #867 * Searching above the root nodes no longer raise exceptions #868 * Msvc detection fixes for non-utf8 encodings #873 * Fixed the destdir processing on Windows #874 * Stop changing the flags on waf -v (make the errors more visible) #875 * Fixed the resource file compilation on Windows #876 * Fixed the vala file installation #881 * New system of plugins for C/C++/Fortran compilers (files named c_* in waflib/extras/) * New examples of interaction between Waf and existing makefiles (playground/) * New names for @before/@after: @before_method/@after_method NEW IN WAF 1.6.2 ---------------- * Support for C# debugging files #797 * Add -relocation-model=pic for shared libraries on ldc * Fixed 'waf dist' for tar files on python 3 #799 * Make the latex scanner recursive #798 * Enable the packing of non-python files in the waf file #802 * Improve the feature sniffing for hybrid programs/libraries #800 * New apidocs + tutorial in Sphinx format * Add the CPPFLAGS from os.environ #803 * Create the java output directory anywhere #806 * Enable the .luac file installation * Process Qt translation files * Detect when the folders were copied and prompt for "waf configure" * Parse_flags for the *-config outputs on windows (backslashes) #811 * Fix the doxygen task build order + improve the dependency scanner #821 * Various msvc fixes #819, #826, #825 * Ported the batch executor to waf 1.6 (batched_cc) * New tools: erlang, scala * Moved conf.multicheck(..) from playground to the library * New parameter to avoid reading the same scripts: bld.recurse(dir, once=True) * Detect invalid method calls in 'waf -v' such as env.append/env.add/env.prepend * New manifest option for jar targets #832 NEW IN WAF 1.6.1 ---------------- * Fixed the method check_waf_version #764 * Fixed the name in ctx.recurse(name) #769 * Stop caching the install tasks and tasks that have no outputs #770 * Fix the log in Context.cmd_and_log() when calling with "quiet" #778 * c_preproc exception when a file has the same name as a directory #777 * 'intltool_po' does not install the .mo files #782 * 'intltool_in' was broken #792 * Bind stderr and stdout to the exception in Context.cmd_and_log #779 * Tasks not rebuilding properly when the 'run' method changes #786 * Print the progress bar information as late as possible #787 * Fix for the FRAMEWORK value processing * Verbose mode should not require the compat15 tools #790 * Let static libraries use other static libraries as in 1.5 #768 * Fix for the boost tool #776 * boost tool update (in playground) #780 * Updated the java tool and examples * New gcj tool in playground * Update the c# tool and examples (playground) #796 * Read external c# libraries #774 * Xelatex support #785 * Rebuild fortran files when .mod files change #766 * docs #781 * Improve the ant_glob behaviour on ctx.root + absolute paths * Fix for glib_mkenums and dbus-binding-tool #795 * New feature 'subst' (see demos/subst) NEW IN WAF 1.6.0 ---------------- General: * Python 3 syntax by default (runs unmodified for 2.6, 2.7, 3.0 and 3.1) * Environment -> ConfigSet * only lists are allowed in ConfigSet * Better Node apis * Utils.load_tool -> Context.load_tool * set_options becomes options * only the build-related commands require a configured project * new variant system + build context commands * removed the pseudo glob in installation methods * eliminate find_sources_in_dirs * node.__class__.bld → node.ctx * bld.new_task_gen(...) disappears, use bld(...) * network updates for waf tools * accept node objects in the source and includes attributes * remove task_gen.allnodes: modify self.source directly * merge the include system for c, c++, d, gas and nasm * allow top == out (no build directory) * merge the Tool/wscript system (detect->configure, set_options->options) * new command "waf list" to list the x for "waf build --targets=x" * rename apply_core -> process_source * rename apply_rule -> process_rule * rename Task.TaskBase.classes -> Task.classes * the modules Utils.py and Logs.py are now independent from the rest of waf (imports) * remove Task.TaskManager and Build.BuildContext.all_task_gen to improve the build group handling * remove program_USELIB, shlib_USELIB staticlib_USELIB support * use tasks for target installation * improve the exception handling (WscriptError was removed, use WafError) * let the commands access node objects * infer the build directory from the lock filename * waf step --file=main.c * post task generators in a lazy manner preview 3: * remove the /W3 flag from msvc default flags * opt.tool_options -> opt.load (now all commands inherit the 'tool' method) * conf.check_tool -> conf.load * do not copy files when creating tar files in 'waf dist' * add zip files in 'waf dist' * fix the behaviour of 'waf distcheck' * preprocessor optimizations * python 2 fixes release candidate: * cache fixes * fortran fixes * python 2 and 3 fixes * docs and docstrings * support for custom waf files and preludes * fix in waflib.Context for overriding command classes * port the doxygen tool * Utils.to_hashtable -> Utils.str2dict * change the thread pool to enable thread pool sharing * fixed a regression on win32 + ansiterm.py + python 3 -> thanks to kesselhaus :-) * various msvc fixes (thanks to Nicolas Mercier) debian/waf-1.7/waf-light0000775000000000000000000001001612145745420012062 0ustar #!/usr/bin/env python # encoding: ISO8859-1 # Thomas Nagy, 2005-2012 """ 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. """ import os, sys VERSION="1.7.10" REVISION="x" INSTALL="x" C1='x' C2='x' cwd = os.getcwd() join = os.path.join if sys.hexversion<0x206000f: raise ImportError('Python >= 2.6 is required to create the waf file') WAF='waf' def b(x): return x if sys.hexversion>0x300000f: WAF='waf3' def b(x): return x.encode() def err(m): print(('\033[91mError: %s\033[0m' % m)) sys.exit(1) def unpack_wafdir(dir): f = open(sys.argv[0],'rb') c = 'corrupt archive (%d)' while 1: line = f.readline() if not line: err('run waf-light from a folder containing waflib') if line == b('#==>\n'): txt = f.readline() if not txt: err(c % 1) if f.readline() != b('#<==\n'): err(c % 2) break if not txt: err(c % 3) txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')) import shutil, tarfile try: shutil.rmtree(dir) except OSError: pass try: for x in ['Tools', 'extras']: os.makedirs(join(dir, 'waflib', x)) except OSError: err("Cannot unpack waf lib into %s\nMove waf in a writable directory" % dir) os.chdir(dir) tmp = 't.bz2' t = open(tmp,'wb') try: t.write(txt) finally: t.close() try: t = tarfile.open(tmp) except: try: os.system('bunzip2 t.bz2') t = tarfile.open('t') tmp = 't' except: os.chdir(cwd) try: shutil.rmtree(dir) except OSError: pass err("Waf cannot be unpacked, check that bzip2 support is present") try: for x in t: t.extract(x) finally: t.close() for x in ['Tools', 'extras']: os.chmod(join('waflib',x), 493) if sys.hexversion<0x300000f: sys.path = [join(dir, 'waflib')] + sys.path import fixpy2 fixpy2.fixdir(dir) os.unlink(tmp) os.chdir(cwd) try: dir = unicode(dir, 'mbcs') except: pass try: from ctypes import windll windll.kernel32.SetFileAttributesW(dir, 2) except: pass def test(dir): try: os.stat(join(dir, 'waflib')) return os.path.abspath(dir) except OSError: pass def find_lib(): name = sys.argv[0] base = os.path.dirname(os.path.abspath(name)) #devs use $WAFDIR w=test(os.environ.get('WAFDIR', '')) if w: return w #waf-light if name.endswith('waf-light'): w = test(base) if w: return w err('waf-light requires waflib -> export WAFDIR=/folder') dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) for i in [INSTALL,'/usr','/usr/local','/opt']: w = test(i + '/lib/' + dirname) if w: return w #waf-local dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) w = test(dir) if w: return w #unpack unpack_wafdir(dir) return dir wafdir = find_lib() sys.path.insert(0, wafdir) if __name__ == '__main__': #import waflib.extras.compat15#PRELUDE from waflib import Scripting Scripting.waf_entry_point(cwd, VERSION, wafdir) debian/waf-1.7/DEVEL0000664000000000000000000000376412145745420011050 0ustar Main repository for waf 1.7 on http://waf.googlecode.com/git/ ------------------------------------------------------------- waflib the core library waflib/Tools essential waf tools waflib/extras contributed tools which are not included in the waf file by default (except "compat15") build_system_kit examples of build systems that can be created from waf tests various unit tests, most are unused anymore playground experiments and integration tests for the tools in the folder waflib/extras demos integration tests - the folder can be configured as a standalone project demos/* integration tests and examples used as documentation docs documentation docs/sphinx project extracting the docstrings from the source code to create the apidocs Documentation repository on http://docs.waf.googlecode.com/git/ --------------------------------------------------------------- Contains the documentation: API documentation http://docs.waf.googlecode.com/git/apidocs_17/index.html The Waf Book http://docs.waf.googlecode.com/git/book_17/single.html The Waf Book for Waf 1.6 (deprecated) http://docs.waf.googlecode.com/git/book_16/single.html The Waf Book for Waf 1.5 (deprecated) http://docs.waf.googlecode.com/git/book_15/single.html Programming details ------------------- * Do not use x.split("\n") but x.splitlines() * Do not catch all exceptions unless you have a good reason to do so * File handles are too easy to get wrong, use Node.readf/Node.writef/Utils.readf/Utils.writef Wiki documentation on http://wiki.waf.googlecode.com/git/ --------------------------------------------------------- ... Previous branches ----------------- old svn repository http://waf.googlecode.com/svn/trunk/ (for waf 1.5, read-only and unused) old branch for waf 1.5 http://waf.googlecode.com/svn/branches/waf-1.5/ (again, read-only and unused) debian/waf-1.7/configure0000775000000000000000000000354712145745420012174 0ustar #! /bin/sh # waf configure wrapper # Fancy colors used to beautify the output a bit. # if [ "$NOCOLOR" ] ; then NORMAL="" BOLD="" RED="" YELLOW="" GREEN="" else NORMAL='\033[0m' BOLD='\033[01;1m' RED='\033[01;91m' YELLOW='\033[00;33m' GREEN='\033[01;92m' fi EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_ERROR=2 EXIT_BUG=10 CUR_DIR=$PWD #possible relative path WORKINGDIR=`dirname $0` cd $WORKINGDIR #abs path WORKINGDIR=`pwd` cd $CUR_DIR # Checks for WAF. Honours $WAF if set. Stores path to 'waf' in $WAF. # Requires that $PYTHON is set. # checkWAF() { printf "Checking for WAF\t\t\t: " #installed miniwaf in sourcedir if [ -z "$WAF" ] ; then if [ -f "${WORKINGDIR}/waf" ] ; then WAF="${WORKINGDIR}/waf" if [ ! -x "$WAF" ] ; then chmod +x $WAF fi fi fi if [ -z "$WAF" ] ; then if [ -f "${WORKINGDIR}/waf-light" ] ; then ${WORKINGDIR}/waf-light --make-waf WAF="${WORKINGDIR}/waf" fi fi #global installed waf with waf->waf.py link if [ -z "$WAF" ] ; then WAF=`which waf 2>/dev/null` fi # neither waf nor miniwaf could be found if [ ! -x "$WAF" ] ; then printf "$RED""not found""$NORMAL""\n" echo "Go to http://code.google.com/p/waf/" echo "and download a waf version" exit $EXIT_FAILURE else printf "$GREEN""$WAF""$NORMAL""\n" fi } # Generates a Makefile. Requires that $WAF is set. # generateMakefile() { cat > Makefile << EOF #!/usr/bin/make -f # Waf Makefile wrapper WAF_HOME=$CUR_DIR all: #@$WAF build all-debug: @$WAF -v build all-progress: @$WAF -p build install: $WAF install --yes; uninstall: $WAF uninstall clean: @$WAF clean distclean: @$WAF distclean @-rm -rf build @-rm -f Makefile check: @$WAF check dist: @$WAF dist .PHONY: clean dist distclean check uninstall install all EOF } checkWAF generateMakefile "${WAF}" configure $* exit $? debian/ns3-doc.doc-base.ns3-models0000664000000000000000000000042211766047442014031 0ustar Document: ns3-models Title: ns-3 Model Library Author: The ns3 Project Abstract: This manual provides documentation about the models of ns-3 Section: Programming/ns3 Format: HTML Index: /usr/share/doc/ns3/models/html/index.html Files: /usr/share/doc/ns3/models/html/*.html debian/compat0000664000000000000000000000000211766047442010401 0ustar 9 debian/libns3-dev.install0000664000000000000000000000010711766112103012522 0ustar usr/lib/libns3.*.so usr/lib/pkgconfig usr/include/* usr/lib/libns3.*.a debian/ns3.lintian-overrides0000664000000000000000000000004312030565566013260 0ustar ns3 binary: binary-without-manpage debian/clean-tree.sh0000664000000000000000000000310112145756421011545 0ustar #!/bin/sh #This script is used clean the source tree,after dpkg-buildpackage -rfakeroot #COPYRIGHT (C) YunQiang Su ,2010. #PUBILIC UNDER GPLv2 or LATER VERSION GPL. #rm ./*.log TOP_DIR=`pwd` NS3_DIR=$TOP_DIR/`ls -d ns-*` PYBINDGENV_DIR=$TOP_DIR/`ls -d pybindgen-0.*` NSC_DIR=$TOP_DIR/`ls -d nsc-*` DEBIAN_DIR=$TOP_DIR/debian echo $DEBIAN_DIR ############################################### #clean top dir cd $TOP_DIR rm -f *.pyc *-stamp ############################################## # build waf cd $DEBIAN_DIR/waf-1.6 ./configure make distclean mv waf $NS3_DIR find -name *.pyc | xargs rm -f cd $DEBIAN_DIR/waf-1.7 ./configure make distclean mv waf $PYBINDGENV_DIR find -name *.pyc | xargs rm -f ################################################ #clean ns3 dir cd $NS3_DIR rm -f ./doc/introspected-doxygen.h ./doc/ns3-object.txt \ ./doc/doxygen.warnings.log ./doc/ns3_html_theme/static/ns3_version.js rm -rf ./doc/html \ ./doc/latex make clean -C ./doc/manual make clean -C ./doc/tutorial make clean -C ./doc/models rm ./different.pcap ./waf clean ./waf distclean ./bindings/python/waf clean ./bindings/python/waf distclean rm -rf ./build-* find . -name '*.pyc' -exec rm {} \; find . -name '.waf-*' -exec rm -rf {} \; rm waf cd $PYBINDGENV_DIR find . -name '*.pyc' -exec rm {} \; find . -name '.waf-*' -exec rm -rf {} \; rm waf cd $NSC_DIR ./scons.py -c rm linux-2.6.18/include/asm rm linux-2.6.26/include/asm rm ./config.log find . -name '*.pyc' -exec rm {} \; find . -name '.waf-*' -exec rm -rf {} \; rm -rf .sconf_temp rm .sconsign.dblite exit 0 debian/ns3.install0000664000000000000000000000001211766047442011267 0ustar usr/bin/* debian/libns3-3.install0000664000000000000000000000002611766112043012111 0ustar usr/lib/libns3.*.so.* debian/copyright0000664000000000000000000005412411766047442011144 0ustar This work was packaged for Debian by: YunQiang Su on Tue, 09 Mar 2010 20:23:41 +0800 It was downloaded from http://www.nsnam.org/releases/ Upstream Authors: NS-3: Kirill Andreev (andreev@iitp.ru) Nicola Baldo (nbaldo@cttc.es) Mirko Banchi (mk.banchi@gmail.com) Ramon Bauza (monbauza@gmail.com) Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu) Raj Bhattacharjea (raj.b@gatech.edu) Timo Bingmann (timo.bingmann@student.kit.edu) Pavel Boyko (boyko@iitp.ru) Jonathan Brugge (j.d.brugge@student.utwente.nl) Elena Buchatskaia (borovkovaes@iitp.ru) Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com) Angelos Chatzipapas (chatzipa@ceid.upatras.gr) Luis Cortes (cortes@gatech.edu) Craig Dowell (craigdo@ee.washington.edu) David Gross (gdavid.devel@gmail.com) Mohamed Amine Ismail (amine.ismail@sophia.inria.fr, iamine@udcast.com) Tom Henderson (tomhend@u.washington.edu) Sam Jansen (sam.jansen@gmail.com) Liu Jian (liujatp@gmail.com) Joe Kopena (tjkopena@cs.drexel.edu) Aleksey Kovalenko (kovalenko@iitp.ru) Mathieu Lacage (mathieu.lacage@sophia.inria.fr) Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca) Keith Ma (keith.nwsuaf@gmail.com) Federico Maguolo (maguolof@dei.unipd.it) Antti Makela (zarhan@cc.hut.fi) Francesco Malandrino (francesco.malandrino@gmail.com) Fabian Mauchle (f1mauchl@hsr.ch) Andrey Mazo (mazo@iitp.ru) Faker Moatamri (faker.moatamri@sophia.inria.fr) Michael Nowatkowski (nowatkom@gmail.com) Duy Nguyen (duy@soe.ucsc.edu) Tommaso Pecorella (tommaso.pecorella@unifi.it) Yana Podkosova (yanapdk@rambler.ru) Guangyu Pei (guangyu.pei@boeing.com) George F. Riley (riley@ece.gatech.edu) Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu) Guillaume Seguin (guillaume.seguin@sophia.inria.fr) Kulin Shah (m.kulin@gmail.com) Phillip Sitbon (phillip.sitbon@gmail.com) Ewgenij Starostin (estar@cs.tu-berlin.de) Adrian S. W. Tam (adrian.sw.tam@gmail.com) Wilson Thong (wilsonwk@ee.cityu.edu.hk) Mauro Tortonesi (mauro.tortonesi@unife.it) Andras Varga (andras@omnetpp.org) Sebastien Vincent (vincent@clarinet.u-strasbg.fr) Guillaume Vu-Brugier (gvubrugier@gmail.com) Tom Wambold (tom5760@gmail.com) Florian Westphal (fw@strlen.de) Josh Pelkey (jpelkey@gatech.edu) PyBindGen: Gustavo J. A. M. Carneiro Network Simulation Cradle: Sam Jansen sam@wand.net.nz WAND Network Research Group Department of Computer Science, University of Waikato, Hamilton, New Zealand Florian Westphal - ns-3 support, Linux 2.6.26, lots of other work And Others SCons: The SCons Foundation WAF: Thomas Nagy and others Copyright and License: NS-3 is copyright under GNU GENERAL PUBLIC LICENSE Version 2. Network Simulation Cradle is copyright under GNU GENERAL PUBLIC LICENSE Version 2. nsc-*/linux-2.6*/* (from linux headers) GNU GENERAL PUBLIC LICENSE Version 2. Copyright (c) Linus Torvalds and others nsc-*/freebsd5/* (From FreeBSD) Copyright (c) FreeBSD team and others * 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. * 3. Neither the name of the copyright holder nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``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 THE PROJECT 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. nsc-*/lwip-*/* * Copyright (c) 2001, 2002 Swedish Institute of Computer Science. * 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. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. * * This file is part of the lwIP TCP/IP stack. * * Author: Adam Dunkels nsc-*/openbsd3/* (From OpenBSD) * Copyright (c) 1982, 1986, 1990, 1991, 1993 * The Regents of the University of California. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS 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. PyBindGen is copyright under GNU LESSER GENERAL PUBLIC LICENSE Version 2.1. Copyright and license for SCons - a software construction tool This copyright and license do not apply to any other software with which this software may have been included. Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. bindings/python/rad_util.py: Copyright (c) 2007 RADLogic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. bindings/python/topsort.py: Copyright (C) 2007 RADLogic IS under GNU LESSER GENERAL PUBLIC LICENSE Version 2.1. examples/flowmon/wif-olsr-flowmon.py: Copyright (c) 2009 INESC Porto IS under GNU General Public License version 2. examples/ipv6/test-ipv6.cc: Copyright (c) 2008 Louis Pasteur University/Telecom Bretagne IS under GNU General Public License version 2. examples/ipv6/radvd-two-prefix.cc,radvd.cc,loose-routing-ipv6.cc icmpv6-redirect.cc: Copyright (c) 2009 Strasbourg University IS under GNU General Public License version 2. examples/ipv6/ping6.cc,fragmentation.cc: Copyright (c) 2008-2009 Strasbourg University IS under GNU General Public License version 2. examples/mesh/mesh.cc: Copyright (c) 2008,2009 IITP RAS IS under GNU General Public License version 2. examples/routing/aodv.cc: Copyright (c) 2009 IITP RAS IS under GNU General Public License version 2. examples/routing/nms_p2p_nix.cc: This topology replicates the original NMS Campus Network model with the exception of chord links (which were never utilized in the original model) Link Bandwidths and Delays may not be the same as the original specifications (c)2009, GTech Systems, Inc. - Alfred Park examples/routing/simple-routing-ping6.cc,simple-routing-ping6.py: Copyright (c) 2008-2009 Strasbourg University IS under GNU General Public License version 2. examples/stats/ Author: Joe Kopena IS under GNU General Public License version 2. examples/tunneling/virtual-net-device.cc: Originally authored by Steve McCanne, 12/19/1996 IS under GNU General Public License version 2. examples/wireless/wifi-ap.py: Copyright (c) 2005,2006,2007 INRIA Copyright (c) 2009 INESC Porto Authors: Mathieu Lacage Gustavo Carneiro IS under GNU General Public License version 2. examples/wireless/wifi-clear-channel-cmu.cc: Copyright (c) 2009 The Boeing Company Author: Guangyu Pei IS under GNU General Public License version 2. examples/wireless/wifi-simple-adhoc.cc,wifi-simple-infra wifi-simple-interference.cc: Copyright (c) 2009 The Boeing Company IS under GNU General Public License version 2. examples/wireless/wifi-simple-adhoc-grid.cc: Copyright (c) 2009 University of Washington IS under GNU General Public License version 2. examples/wireless/wifi-ap.cc,wifi-adhoc.cc: Copyright (c) 2005,2006,2007 INRIA Author: Mathieu Lacage IS under GNU General Public License version 2. examples/wireless/simple-wifi-frame-aggregation.cc Copyright (c) 2009 MIRKO BANCHI Author: Mirko Banchi IS under GNU General Public License version 2. examples/wireless/multirate.cc: Author: Duy Nguyen IS under GNU General Public License version 2. all other files in examples/: IS under GNU General Public License version 2. pybindgen-0.*/pybindgen/ typehandlers/ctypeparser/tokenizer.py: Copyright 2007 Neal Norwitz Portions Copyright 2007 Google Inc. Licensed under the Apache License, Version 2.0. all other files in pybindgen-0.*/ : AUTHOR: Gustavo J. A. M. Carneiro IS under GNU LESSER GENERAL PUBLIC LICENSE Version 2.1. samples/main-attribute-value.cc: Copyright (c) 2008 University of Washington Author: Tom Henderson IS under GNU General Public License version 2. samples/main-packet-tag.cc: Copyright (c) 2006,2007 INRIA Author: Mathieu Lacage IS under GNU General Public License version 2. samples/main-propagation-loss.cc,main-random-variable.cc: Copyright (c) 2008 Timo Bingmann Author: Timo Bingmann IS under GNU General Public License version 2. samples/main-tw.cc: Copyright (c) 2007 University of Washington IS under GNU General Public License version 2. samples/sample-random-variable.cc: IS under GNU General Public License version 2. utils/bench-packets.cc,bench-simulator: Copyright (c) 2006 INRIA Author: Mathieu Lacage IS under GNU General Public License version 2. utils/test-runner.cc: Copyright (c) 2009 University of Washington utils/Iconv/genhtml: Copyright (c) International Business Machines Corp., 2002 IS under GPLv2 or (at your option) any later version. History: 2002-08-23 created by Peter Oberparleiter IBM Lab Boeblingen based on code by Manoj Iyer and Megan Bock IBM Austin 2002-08-27 Peter Oberparleiter: implemented frame view 2002-08-29 Peter Oberparleiter: implemented test description filtering so that by default only descriptions for test cases which actually hit some source lines are kept 2002-09-05 Peter Oberparleiter: implemented --no-sourceview 2002-09-05 Mike Kobler: One of my source file paths includes a "+" in the directory name. I found that genhtml.pl died when it encountered it. I was able to fix the problem by modifying the string with the escape character before parsing it. 2002-10-26 Peter Oberparleiter: implemented --num-spaces 2003-04-07 Peter Oberparleiter: fixed bug which resulted in an error when trying to combine .info files containing data without a test name 2003-04-10 Peter Oberparleiter: extended fix by Mike to also cover other special characters 2003-04-30 Peter Oberparleiter: made info write to STDERR, not STDOUT 2003-07-10 Peter Oberparleiter: added line checksum support 2004-08-09 Peter Oberparleiter: added configuration file support utils/geninfo: Copyright (c) International Business Machines Corp., 2002 IS under GPLv2 or (at your option) any later version. Authors: 2002-08-23 created by Peter Oberparleiter IBM Lab Boeblingen based on code by Manoj Iyer and Megan Bock IBM Austin 2002-09-05 Peter Oberparleiter: implemented option that allows file list 2003-04-16 Peter Oberparleiter: modified read_gcov so that it can also parse the new gcov format which is to be introduced in gcc 3.3 2003-04-30 Peter Oberparleiter: made info write to STDERR, not STDOUT 2003-07-03 Peter Oberparleiter: added line checksum support, added --no-checksum 2003-09-18 Nigel Hinds: capture branch coverage data from GCOV 2003-12-11 Laurent Deniel: added --follow option workaround gcov (<= 3.2.x) bug with empty .da files 2004-01-03 Laurent Deniel: Ignore empty .bb files 2004-02-16 Andreas Krebbel: Added support for .gcno/.gcda files and gcov versioning 2004-08-09 Peter Oberparleiter: added configuration file support utils/Iconv: Copyright (c) International Business Machines Corp., 2002 IS under GPLv2 or (at your option) any later version. History: 2002-08-29 created by Peter Oberparleiter IBM Lab Boeblingen 2002-09-05 Peter Oberparleiter: implemented --kernel-directory + multiple directories 2002-10-16 Peter Oberparleiter: implemented --add-tracefile option 2002-10-17 Peter Oberparleiter: implemented --extract option 2002-11-04 Peter Oberparleiter: implemented --list option 2003-03-07 Paul Larson: Changed to make it work with the latest gcov kernel patch.This will break it with older gcov-kernel patches unless you change the value of $gcovmod in this script 2003-04-07 Peter Oberparleiter: fixed bug which resulted in an error when trying to combine .info files containing data without a test name 2003-04-10 Peter Oberparleiter: extended Paul's change so that LCOV works both with the new and the old gcov-kernel patch 2003-04-10 Peter Oberparleiter: added $gcov_dir constant in anticipation of a possible move of the gcov kernel directory to another file system in a future version of the gcov-kernel patch 2003-04-15 Paul Larson: make info write to STDERR, not STDOUT 2003-04-15 Paul Larson: added --remove option 2003-04-30 Peter Oberparleiter: renamed --reset to --zerocounters to remove naming ambiguity with --remove 2003-04-30 Peter Oberparleiter: adjusted help text to include --remove 2003-06-27 Peter Oberparleiter: implemented --diff 2003-07-03 Peter Oberparleiter: added line checksum support, added --no-checksum 2003-12-11 Laurent Deniel: added --follow option 2004-03-29 Peter Oberparleiter: modified --diff option to better cope with ambiguous patch file entries, modified --capture option to use modprobe before insmod (needed for 2.6) 2004-03-30 Peter Oberparleiter: added --path option 2004-08-09 Peter Oberparleiter: added configuration file support waf-tools/pkg_config.py: Gustavo Carneiro (gjamc) 2008 waf-tools/shellcmd.py: Copyright (C) 2008 Gustavo J. A. M. Carneiro IS under GPLv2 or (at your option) any later version. debian/waf-*/*: 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. The Debian packaging is: Copyright (C) 2010 YunQiang Su and is licensed under the GPL version 2. Please go to /usr/share/common-licenses/GPL-2 to view GPLv2 Please go to /usr/share/common-licenses/LGPL-2 to view LGPLv2.1 debian/source/0000775000000000000000000000000011766047442010503 5ustar debian/source/format0000664000000000000000000000001411766047442011711 0ustar 3.0 (quilt) debian/source/include-binaries0000664000000000000000000000024011766047442013637 0ustar debian/upstream-back/manual-figures/plot-2d.png debian/upstream-back/manual-figures/plot-2d-with-error-bars.png debian/upstream-back/manual-figures/plot-3d.png debian/manpages/0000775000000000000000000000000011766047442010776 5ustar debian/manpages/bench-simulator.10000664000000000000000000000143611766047442014160 0ustar .\" Process this file with .\" groff -man -Tascii bench-simulator.1 .\" .TH bench-simulator 1 "MARCH 2010" Linux "User Manuals" .SH NAME bench-simulator \- run simulator bench .SH SYNOPSIS .B bench-simulator filename [--[list|map|heap|debug]] [--n=TIMES] .SH DESCRIPTION .B bench-simulator run simulator bench filename: a string which identifies the input distribution. "-" represents stdin. .SH OPTIONS .IP --list use std::list scheduler .IP --map use std::map cheduler .IP --heap use Binary Heap scheduler .IP --debug enable some debugging .IP --n=TIMES run TIMES times bench .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR wifi-phy-test .BR emu-sock-creator (1) .BR tap-creator (1) .BR simple (1) .BR multiple-sources (1) .BR bench-packets (1) debian/manpages/scratch-simulator.10000664000000000000000000000067011766047442014527 0ustar .\" Process this file with .\" groff -man -Tascii scratch-simulator.1 .\" .TH scratch-simulator 1 "May 2011" Linux "User Manuals" .SH NAME tap-creator \- just a demo .SH DESCRIPTION .B just a demo to test modules. .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR emu-sock-creator (1) .BR bench-simulator (1) .BR bench-packets (1) .BR simple (1) .BR multiple-sources (1) .BR wifi-phy-test (1) debian/manpages/wifi-phy-test.10000664000000000000000000000141511766047442013572 0ustar .\" Process this file with .\" groff -man -Tascii wifi-phy-test.1 .\" .TH wifi-phy-test 1 "MARCH 2010" Linux "User Manuals" .SH NAME wifi-phy-test \- run WiFi PHY test .SH SYNOPSIS .B wifi-phy-test experiment .SH DESCRIPTION .B wifi-phy-test run WiFi PHY test with given experiment .SH Available experiments .IP Psr Packet Success Rate .IP SizeVsRange Size Vs Range .IP PsrVsDistance Psr Vs Distance .IP PsrVsCollisionInterval Psr Vs CollisionInterval .SH BUGS When using SizeVsRange, PsrVsDistance, PsrVsCollisionInterval, it will encounter sgement fault. .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR emu-sock-creator (1) .BR bench-simulator (1) .BR tap-creator (1) .BR simple (1) .BR multiple-sources (1) .BR bench-packets (1) debian/manpages/tap-creator.10000664000000000000000000000160311766047442013301 0ustar .\" Process this file with .\" groff -man -Tascii tap-creators.1 .\" .TH tap-creator 1 "MARCH 2010" Linux "User Manuals" .SH NAME tap-creator \- emulate tap creator .SH SYNOPSIS .B tap-creator -d DEV -g GATEWAY -i IPADDR .B -m MACADDR -n NETMASK -o MODE -p PATH [-v] .SH DESCRIPTION .B emulate tap creator with given parameters .SH OPTIONS .IP "-d DEV" name of the new tap device .IP "-g GATEWAY" gateway address for the new device .IP "-i IPADDR" ip address of the new device .IP "-m MACADDR" mac address of the new device .IP "-n NETMASK" net mask for the new device .IP "-o MODE" operating mode of tap bridge .IP "-p PATH" path back to the tap bridge .IP -v be verbose .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR emu-sock-creator (1) .BR bench-simulator (1) .BR bench-packets (1) .BR simple (1) .BR multiple-sources (1) .BR wifi-phy-test (1) debian/manpages/bench-packets.10000664000000000000000000000116111766047442013566 0ustar .\" Process this file with .\" groff -man -Tascii bench-packets.1 .\" .TH bench-packets 1 "MARCH 2010" Linux "User Manuals" .SH NAME bench-packets \- run packets bench with NUMBER packets .SH SYNOPSIS .B bench-packets --n=NUMBER [--enable-printing] .SH DESCRIPTION .B run packets bench with NUMBER packets .SH OPTIONS .IP --n=NUMBER with NUMBER packets,run bench .IP --enable-printing enable printing .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR emu-sock-creator (1) .BR bench-simulator (1) .BR tap-creator (1) .BR simple (1) .BR multiple-sources (1) .BR wifi-phy-test (1) debian/manpages/print-introspected-doxygen.10000664000000000000000000000100211766047442016361 0ustar .\" Process this file with .\" groff -man -Tascii print-introspected-doxygen.1 .\" .TH print-introspected-doxygen 1 "MARCH 2010" Linux "User Manuals" .SH NAME print-introspected-doxygen \- print the code of introspected doxygen .SH DESCRIPTION .B print the code of introspected doxygen without options. .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR multiple-sources (1) .BR bench-packets (1) .BR bench-simulator (1) .BR tap-creator (1) .BR simple (1) .BR emu-sock.creator (1) .BR wifi-phy-test (1) debian/manpages/emu-sock-creator.10000664000000000000000000000107311766047442014241 0ustar .\" Process this file with .\" groff -man -Tascii emu-sock-creator.1 .\" .TH emu-sock-creator 1 "MARCH 2010" Linux "User Manuals" .SH NAME emu-sock-creator \- emulate socket creator .SH SYNOPSIS .B emu-sock-creator -p PATH [-v] .SH DESCRIPTION .B emulate socket creator to given PATH .SH OPTIONS .IP "-p PATH" PATH set path to PATH .IP -v be verbose .SH AUTHOR YunQiang Su .SH "SEE ALSO" .BR print-introspected-doxygen (1) .BR bench-packets (1) .BR bench-simulator (1) .BR tap-creator (1) .BR simple (1) .BR multiple-sources (1) .BR wifi-phy-test (1) debian/python-ns3.install0000664000000000000000000000002511766047442012612 0ustar /usr/lib/python2.*/* debian/README.Debian0000664000000000000000000000043712114121141011221 0ustar ns-3 package for Debian ----------------------- This package is not binary compatible now. It will break every new upstream release. It is still in heavy development. DFSG: remove ns-3.*/waf and pybindgen-*/waf -- YunQiang Su Wed, 13 Jun 2012 16:13:28 +0800 debian/ns3-doc.install0000664000000000000000000000035511766047442012044 0ustar ns-3.*/doc/manual/build/html/* usr/share/doc/ns3/manual/html/ ns-3.*/doc/tutorial/build/html/* usr/share/doc/ns3/tutorial/html/ ns-3.*/doc/models/build/html/* usr/share/doc/ns3/models/html/ ns-3.*/doc/html/* usr/share/doc/ns3/doxygen debian/ns3-doc.links0000664000000000000000000000125311766047442011514 0ustar /usr/share/javascript/sphinxdoc/1.0/jquery.js /usr/share/doc/ns3/manual/html/_static/jquery.js /usr/share/javascript/sphinxdoc/1.0/jquery.js /usr/share/doc/ns3/models/html/_static/jquery.js /usr/share/javascript/sphinxdoc/1.0/jquery.js /usr/share/doc/ns3/tutorial/html/_static/jquery.js /usr/share/javascript/sphinxdoc/1.0/underscore.js /usr/share/doc/ns3/manual/html/_static/underscore.js /usr/share/javascript/sphinxdoc/1.0/underscore.js /usr/share/doc/ns3/models/html/_static/underscore.js /usr/share/javascript/sphinxdoc/1.0/underscore.js /usr/share/doc/ns3/tutorial/html/_static/underscore.js /usr/share/javascript/sphinxdoc/1.0/jquery.js /usr/share/doc/ns3/doxygen/jquery.js debian/duplicate-files.py0000664000000000000000000000061012114345256012614 0ustar #!/usr/bin/env python import sys import os import os.path md5_file=sys.argv[1] f=open(md5_file) c=f.readlines() print "File count before deduplicate: %s." % (len(c)) removed_count=0 pre=['', ''] for i in c: l=i.strip().split(' ') if pre[0] == l[0]: os.remove(l[1]) os.symlink(pre[1], l[1]) removed_count+=1 else: pre = l f.close() print "We removed %s files" % (removed_count) debian/ns3-doc.doc-base.ns3-manual0000664000000000000000000000036411766047442014030 0ustar Document: ns3-manual Title: The ns3 Manual Author: The ns3 Project Abstract: This is an ns-3 reference manual. Section: Programming/ns3 Format: HTML Index: /usr/share/doc/ns3/manual/html/index.html Files: /usr/share/doc/ns3/manual/html/*.html debian/ns3-doc.manpages0000664000000000000000000000014212030565214012146 0ustar ns-3.*/doc/manual/build/man/*.1 ns-3.*/doc/tutorial/build/man/*.1 ns-3.*/doc/models/build/man/*.1 debian/ns3-doc.doc-base.ns3-tutorial0000664000000000000000000000036011766047442014412 0ustar Document: ns3-tutorial Title: ns-3 tutorial Author: The ns3 Project Abstract: This is an ns-3 tutorial Section: Programming/ns3 Format: HTML Index: /usr/share/doc/ns3/tutorial/html/index.html Files: /usr/share/doc/ns3/tutorial/html/*.html debian/control0000664000000000000000000001340012114163433010567 0ustar Source: ns3 Section: net Priority: optional Standards-Version: 3.9.4 Maintainer: Debian Network Simulators Team DM-Upload-Allowed: yes Uploaders: YunQiang Su Build-Depends: debhelper (>= 9), quilt (>= 0.46-7~), pkg-config, python-dev, libxml2-dev, libgsl0-dev, libsqlite3-dev, libgraphviz-dev, flex, bison, libboost-signals-dev, libboost-filesystem-dev, python-pygoocanvas, python-pygraphviz, libopenmpi-dev [alpha amd64 hurd-i386 i386 ia64 kfreebsd-amd64 kfreebsd-i386 powerpc sparc] Build-Depends-Indep: dia, doxygen, python-sphinx, texlive-font-utils, optipng, ghostscript, texlive-latex-extra, texlive-latex-base, texlive-latex-recommended, imagemagick, Build-Conflicts: libmpich2-dev Vcs-git: git://git.debian.org/pkg-netsim/ns3.git Vcs-Browser: http://anonscm.debian.org/gitweb/?p=pkg-netsim/ns3.git Homepage: http://www.nsnam.org/ Package: ns3 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: discrete-event network simulator for Internet systems ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains several utilities. The files for development are in libns3-3, libns3-dev and python-ns3. Package: ns3-doc Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, libjs-jquery Section: doc Description: documentation for ns3 ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains manual, modules, tutorial and doxygen. Package: libns3-3 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: shared libraries of ns-3 ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains shared libraries. Package: libns3-3-dbg Architecture: any Section: debug Priority: extra Depends: ${shlibs:Depends}, ${misc:Depends}, libns3-3 Description: shared libraries of ns-3 (debug extension) ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains shared libraries. . This package contains the debugging symbols. Package: libns3-dev Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Section: libdevel Description: Static and header files of ns-3 ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains static libraries, header files. Package: python-ns3 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends} Section: python Suggests: python-pygraphviz, python-kiwi, python-pygoocanvas, tcpdump Description: Python binding of ns3 ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains Python binding of ns3. Package: python-ns3-dbg Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-ns3 Section: debug Priority: extra Suggests: python-pygraphviz, python-kiwi, python-pygoocanvas, tcpdump Description: Python binding of ns3 (debug extension) ns-3 is a discrete-event network simulator for Internet systems, targeted primarily for research and educational use. ns-3 is free software, licensed under the GNU GPLv2 license, and is publicly available for research, development, and use. ns-3 is intended as an eventual replacement for the popular ns-2 simulator. The project acronym “nsnam” derives historically from the concatenation of ns (network simulator) and NAM (network animator). . This package contains Python binding of ns3. . This package contains the debugging symbols. debian/docs0000664000000000000000000000004311766047442010053 0ustar ns-3.*/README ns-3.*/RELEASE_NOTES debian/waf-1.6/0000775000000000000000000000000012253225220010242 5ustar debian/waf-1.6/utils/0000775000000000000000000000000012145744415011416 5ustar debian/waf-1.6/utils/launcher/0000775000000000000000000000000012145744415013217 5ustar debian/waf-1.6/utils/launcher/wscript0000664000000000000000000000025112145744415014633 0ustar out = 'waf-launcher/bin/Release' def configure(config): config.load('cs') def build(bld): bld(features='cs',source='waf-launcher/Main.cs', type='exe',gen='waf.exe') debian/waf-1.6/utils/launcher/README.md0000664000000000000000000000252412145744415014501 0ustar #Waf-launcher This is a simple wrapper for the [waf build system](http://code.google.com/p/waf/) Since many windows users does not have python installed by default, the exe file from this project can be included along with the copy of waf to wrap waf to install python on demand. The requirements is only .Net 2.0 whics is either Windows Server 2003 R2 and up, or Windows Vista and up. There is a good chance it is installed in many OEM installs of Windows XP as well ##How to compile use either waf or monodevelop (wscript and project files is in the repository) ##How to use Assume we have a repository, myrepo, where wscript and waf already exists. myrepo/waf myrepo/wscript now copy waf-launcher/bin/Release/waf.exe to the repository myrepo/waf.exe Linux users can continue to use `./waf`, just like Windows users can continue to use `python waf` For Windows users there is now a second way to invoke waf by writing either `waf.exe` or simply just `waf`. When the Windows users does that the following happens: 1. It tries "python waf" 2. If 1 failed it tries "C:\python27\python.exe waf" 3. If 2 failed it ask for permission to install python 4. If pemission is given it tries to install python silently 5. step 1 and 2 it done again 6. If this still fails we exit with an error Any arguments to `waf.exe` is passed on to `waf` debian/waf-1.6/utils/launcher/waf-launcher.sln0000664000000000000000000000163012145744415016311 0ustar  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "waf-launcher", "waf-launcher\waf-launcher.csproj", "{63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Debug|x86.ActiveCfg = Debug|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Debug|x86.Build.0 = Debug|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Release|x86.ActiveCfg = Release|x86 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = waf-launcher\waf-launcher.csproj version = 1.0 EndGlobalSection EndGlobal debian/waf-1.6/utils/launcher/LICENSE0000664000000000000000000000247212145744415014231 0ustar 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. debian/waf-1.6/utils/launcher/waf-launcher/0000775000000000000000000000000012145744415015573 5ustar debian/waf-1.6/utils/launcher/waf-launcher/Main.cs0000664000000000000000000000646712145744415017023 0ustar using System; using System.Diagnostics; namespace waflauncher { class MainClass { public static System.Diagnostics.Process exec(string command,params string[] args) { String argstring = String.Join(" ",args); System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo(command,argstring); startinfo.UseShellExecute = false; System.Diagnostics.Process p; try { p = Process.Start(startinfo); } catch (System.ComponentModel.Win32Exception){ return null; } p.WaitForExit(); return p; } public static int Main (string[] args) { //I run waf and if not succesful we try on-the-fly install of python if(!runWaf(args)){ //but first we ask the user if it's okay to install software on their computer if(mayInstall()){ //I install python and try running waf yet another time installPython(); if(!runWaf(args)){ //If it still fails something has gone horrible wrong Console.WriteLine("Python not fully working"); return 1; } } else { Console.WriteLine("Not automatically installing Python"); Console.WriteLine("Please download and install http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi"); Console.WriteLine("or if you have python installed make sure it is on %PATH%"); Console.WriteLine("or run this command again and answer yes"); } } return 0; } public static bool mayInstall() { Console.Write("Download and install python [Y/n]? "); ConsoleKeyInfo a = Console.ReadKey(); Console.WriteLine(); switch(a.KeyChar){ case 'Y': case 'y': case '\n': case '\r': return true; //If unsure default to not doing it default: return false; } } public static String getwafDir(){ //This changes the current directory to the place where the exe exists System.Reflection.Assembly a = System.Reflection.Assembly.GetEntryAssembly(); String path = System.IO.Path.GetDirectoryName(a.Location); return path + System.IO.Path.DirectorySeparatorChar; } public static bool runWaf(string[] args){ Process p = exec("python", getwafDir() + "waf", String.Join(" ",args)); //If command could be execeuted return true if (p != null) return true; //If not try with the direct path to the default installation which is where installPython() will install it to //This is done since the %PATH% variable might not be setup to include python List versions = new List() { "27", "32", "26", "31", "25", "30" }; foreach (String v in versions) { p = exec("C:\\Python"+v+"\\python.exe", "waf", String.Join(" ",args)); if (p != null) return true; } return false; } public static void installPython(){ //Make a filename to download python to String filename = System.IO.Path.GetTempPath() + Char.ToString(System.IO.Path.DirectorySeparatorChar) + "python-2.7.1.msi"; System.Net.WebClient web = new System.Net.WebClient(); Console.WriteLine ("Downloading python 2.7"); web.DownloadFile("http://www.python.org/ftp/python/2.7.1/python-2.7.1.msi",filename); Console.WriteLine ("python2.7 downloaded to " + filename); Console.WriteLine ("Installing python"); //filename must be qouted or else msiexec will fail exec("msiexec","/qn","/i","\"" +filename + "\""); Console.WriteLine ("Python is now installed"); } } } debian/waf-1.6/utils/launcher/waf-launcher/AssemblyInfo.cs0000664000000000000000000000172212145744415020517 0ustar using System.Reflection; using System.Runtime.CompilerServices; // Information about this assembly is defined by the following attributes. // Change them to the values specific to your project. [assembly: AssemblyTitle("waf-launcher")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("")] [assembly: AssemblyCopyright("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. //[assembly: AssemblyDelaySign(false)] //[assembly: AssemblyKeyFile("")] debian/waf-1.6/utils/launcher/waf-launcher/waf-launcher.csproj0000664000000000000000000000361412145744415021375 0ustar Debug x86 9.0.21022 2.0 {63E79792-BE8F-4AE5-9A99-99B1AE4D96E3} Exe waflauncher waf v3.5 1.0 true full false bin\Debug DEBUG prompt 4 x86 true none false bin\Release prompt 4 x86 true debian/waf-1.6/utils/genbench.py0000775000000000000000000002253512145744415013553 0ustar #!/usr/bin/python # encoding: utf-8 import sys import os.path from random import Random random = Random(0) # initialise with seed to have reproductible benches # for example: ./genbench.py /tmp/build 50 100 15 5 HELP_USAGE = """Usage: generate_libs.py root libs classes internal external. root - Root directory where to create libs. libs - Number of libraries (libraries only depend on those with smaller numbers) classes - Number of classes per library internal - Number of includes per file referring to that same library external - Number of includes per file pointing to other libraries To try the waf part, do: waf configure build -p -j5 To test the autotools part, do: touch README AUTHORS NEWS ChangeLog && autoreconf --install --symlink --verbose && mkdir autotools-build-dir && cd autotools-build-dir && ../configure --disable-shared CXXFLAGS=-Wall && time make -j4 --silent && time make -j4 --silent """ def lib_name(i): return "lib_" + str(i) def createHeader(name): filename = name + ".h" handle = file(filename, "w" ) guard = name + '_h_' handle.write ('#ifndef ' + guard + '\n'); handle.write ('#define ' + guard + '\n\n'); handle.write ('class ' + name + ' {\n'); handle.write ('public:\n'); handle.write (' ' + name + '();\n'); handle.write (' ~' + name + '();\n'); handle.write ('};\n\n'); handle.write ('#endif\n'); def createCPP(name, lib_number, classes_per_lib, internal_includes, external_includes): filename = name + ".cpp" handle = file(filename, "w" ) header= name + ".h" handle.write ('#include "' + header + '"\n'); includes = random.sample(range(classes_per_lib), internal_includes) for i in includes: handle.write ('#include "class_' + str(i) + '.h"\n') if (lib_number > 0): includes = random.sample(range(classes_per_lib), external_includes) lib_list = range(lib_number) for i in includes: libname = 'lib_' + str(random.choice(lib_list)) handle.write ('#include <' + libname + '/' + 'class_' + str(i) + '.h>\n') handle.write ('\n'); handle.write (name + '::' + name + '() {}\n'); handle.write (name + '::~' + name + '() {}\n'); def createSConscript(lib_number, classes): handle = file("SConscript", "w"); handle.write("Import('env')\n") handle.write('list = Split("""\n'); for i in range(classes): handle.write(' class_' + str(i) + '.cpp\n') handle.write(' """)\n\n') handle.write('env.StaticLibrary("lib_' + str(lib_number) + '", list)\n\n') def createLibCMakeLists(lib_number, classes): handle = file("CMakeLists.txt", "w") handle.write("""add_library(lib_%s STATIC %s)\n""" % (str(lib_number), ' '.join(('class_%s' % str(i) for i in range(classes))))) def createLibMakefile(lib_number, classes): handle = file("Makefile", "w"); handle.write ("""COMPILER = g++ INC = -I.. CCFLAGS = -g -Wall $(INC) ARCHIVE = ar DEPEND = makedepend .SUFFIXES: .o .cpp """) handle.write ("lib = lib_" + str(lib_number) + ".a\n") handle.write ("src = \\\n") for i in range(classes): handle.write('class_' + str(i) + '.cpp \\\n') handle.write (""" objects = $(patsubst %.cpp, %.o, $(src)) all: depend $(lib) $(lib): $(objects) $(ARCHIVE) cr $@ $^ touch $@ .cpp.o: $(COMPILER) $(CCFLAGS) -c $< clean: @rm $(objects) $(lib) 2> /dev/null depend: @$(DEPEND) $(INC) $(src) """) def createLibJamFile(lib_number, classes): handle = file("Jamfile", "w") handle.write ("SubDir TOP lib_" + str(lib_number) + " ;\n\n") handle.write ("SubDirHdrs $(INCLUDES) ;\n\n") handle.write ("Library lib_" + str(lib_number) + " :\n") for i in range(classes): handle.write(' class_' + str(i) + '.cpp\n') handle.write (' ;\n') def createVCProjFile(lib_number, classes): handle = file("lib_" + str(lib_number) + ".vcproj", "w") handle.write(""" """) for i in range(classes): handle.write(' \n') handle.write(""" """) def createLibrary(lib_number, classes, internal_includes, external_includes): name = "lib_" + str(lib_number) setDir(name) for i in range(classes): classname = "class_" + str(i) createHeader(classname) createCPP(classname, lib_number, classes, internal_includes, external_includes) createSConscript(lib_number, classes) createLibCMakeLists(lib_number, classes) createLibMakefile(lib_number, classes) createAutotools(lib_number, classes) os.chdir("..") def createCMakeLists(libs): handle = file("CMakeLists.txt", "w") handle.write("""project('profiling-test') cmake_minimum_required(VERSION 2.8) include_directories(${CMAKE_SOURCE_DIR}) """) for i in range(libs): handle.write("""add_subdirectory(lib_%s)\n""" % str(i)) def createSConstruct(libs): handle = file("SConstruct", "w"); handle.write("""env = Environment(CPPFLAGS=['-Wall'], CPPDEFINES=['LINUX'], CPPPATH=[Dir('#')])\n""") handle.write("""env.Decider('timestamp-newer')\n""") handle.write("""env.SetOption('implicit_cache', True)\n""") handle.write("""env.SourceCode('.', None)\n""") for i in range(libs): handle.write("""env.SConscript("lib_%s/SConscript", exports=['env'])\n""" % str(i)) def createFullMakefile(libs): handle = file("Makefile", "w") handle.write('subdirs = \\\n') for i in range(libs): handle.write('lib_' + str(i) + '\\\n') handle.write(""" all: $(subdirs) @for i in $(subdirs); do \ $(MAKE) -C $$i all; done clean: @for i in $(subdirs); do \ (cd $$i; $(MAKE) clean); done depend: @for i in $(subdirs); do \ (cd $$i; $(MAKE) depend); done """) def createFullJamfile(libs): handle = file("Jamfile", "w") handle.write ("SubDir TOP ;\n\n") for i in range(libs): handle.write('SubInclude TOP ' + lib_name(i) + ' ;\n') handle = file("Jamrules", "w") handle.write('INCLUDES = $(TOP) ;\n') WT = """#! /usr/bin/env python # encoding: utf-8 VERSION = '0.0.2' APPNAME = 'build_bench' top = '.' out = 'out' def configure(conf): conf.load('g++') def build(bld): for i in range(%d): filez = ' '.join(['lib_%%d/class_%%d.cpp' %% (i, j) for j in range(%d)]) bld.stlib( source = filez, target = 'lib_%%d' %% i, includes = '.', # include the top-level ) """ def createWtop(libs, classes): f = open('wscript', 'w') f.write(WT % (libs, classes)) f.close() def createFullSolution(libs): handle = file("solution.sln", "w") handle.write("Microsoft Visual Studio Solution File, Format Version 8.00\n") for i in range(libs): project_name = lib_name(i) + '\\' + lib_name(i) + '.vcproj' handle.write('Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "' + lib_name(i) + '", "' + project_name + '", "{CF495178-8865-4D20-939D-AAA' + str(i) + '}"\n') handle.write('EndProject\n') def createAutotoolsTop(libs): handle = file("configure.ac", "w") handle.write('''\ AC_INIT([bench], [1.0.0]) AC_CONFIG_AUX_DIR([autotools-aux]) AM_INIT_AUTOMAKE([subdir-objects nostdinc no-define tar-pax dist-bzip2]) AM_PROG_LIBTOOL AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT ''') handle = file("Makefile.am", "w") handle.write('''\ AM_CPPFLAGS = -I$(srcdir) lib_LTLIBRARIES = ''') for i in range(libs): handle.write('include lib_%s/Makefile.am\n' % str(i)) def createAutotools(lib_number, classes): handle = file("Makefile.am", "w") handle.write('''\ lib_LTLIBRARIES += lib%s.la lib%s_la_SOURCES =''' % (str(lib_number), str(lib_number))) for i in range(classes): handle.write(' lib_%s/class_%s.cpp' % (str(lib_number), str(i))) handle.write('\n') def setDir(dir): if (not os.path.exists(dir)): os.mkdir(dir) os.chdir(dir) def main(argv): if len(argv) != 6: print HELP_USAGE return root_dir = argv[1] libs = int(argv[2]) classes = int(argv[3]) internal_includes = int(argv[4]) external_includes = int(argv[5]) setDir(root_dir) for i in range(libs): createLibrary(i, classes, internal_includes, external_includes) createSConstruct(libs) createCMakeLists(libs) createFullMakefile(libs) createWtop(libs, classes) createAutotoolsTop(libs) if __name__ == "__main__": main( sys.argv ) debian/waf-1.6/utils/waf.bat0000664000000000000000000000414112145744415012663 0ustar @echo off rem from issue #964 Setlocal EnableDelayedExpansion rem Check Windows Version set TOKEN=tokens=3* ver | findstr /i "5\.0\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "5\.1\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "5\.2\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=3* ver | findstr /i "6\.0\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=2* ver | findstr /i "6\.1\." > nul if %ERRORLEVEL% EQU 0 SET TOKEN=tokens=2* rem Start calculating PYTHON and PYTHON_DIR set PYTHON= set PYTHON_DIR= Setlocal EnableDelayedExpansion set PYTHON_DIR_OK=FALSE set REGPATH= for %%i in (3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0 2.7 2.6 2.5 2.4 2.3) do ( for %%j in (HKCU HKLM) do ( for %%k in (SOFTWARE\Wow6432Node SOFTWARE) do ( for %%l in (Python\PythonCore IronPython) do ( set REG_PYTHON_EXE=python.exe if "%%l"=="IronPython" ( set REG_PYTHON_EXE=ipy.exe ) @echo on set REGPATH=%%j\%%k\%%l\%%i\InstallPath rem @echo Regpath !REGPATH! REG QUERY "!REGPATH!" /ve 1>nul 2>nul if !ERRORLEVEL! equ 0 ( for /F "%TOKEN% delims= " %%A IN ('REG QUERY "!REGPATH!" /ve') do @set REG_PYTHON_DIR=%%B if exist !REG_PYTHON_DIR! ( set REG_PYTHON=!REG_PYTHON_DIR!!REG_PYTHON_EXE! rem set PYTHON_DIR_OK=TRUE if "!PYTHON_DIR_OK!"=="FALSE" ( set PYTHON_DIR=!REG_PYTHON_DIR! set PYTHON=!REG_PYTHON! set PYTHON_DIR_OK=TRUE ) rem set PYTHON_DIR_OK=FALSE rem @echo Find !REG_PYTHON! rem goto finished ) ) echo off ) rem for l ) rem for k ) rem for j ) rem for i :finished Endlocal & SET PYTHON_DIR=%PYTHON_DIR% & SET PYTHON=%PYTHON% if "%PYTHON_DIR%" == "" ( rem @echo No Python dir set PYTHON=python goto running ) rem @echo %PYTHON_DIR% if "%PYTHON%" == "" ( rem @echo No Python set PYTHON=python goto running ) set PYTHON_INCLUDE=%PYTHON_DIR%include set PYTHON_LIB=%PYTHON_DIR%libs\python27.lib set PATH=%PYTHON_DIR%;%PYTHON_DIR%Scripts;%PYTHON_DIR%Tools\Scripts;%PATH% :running @echo Using %PYTHON% "%PYTHON%" -x "%~dp0waf" %* & Endlocal & exit /b debian/waf-1.6/wscript0000664000000000000000000002300312145744415011672 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 """ to make a custom waf file use the option --tools To add a tool that does not exist in the folder compat15, pass an absolute path: ./waf-light --make-waf --tools=compat15,/comp/waf/aba.py --prelude=$'\tfrom waflib.extras import aba\n\taba.foo()' """ VERSION="1.6.11" APPNAME='waf' REVISION='' top = '.' out = 'build' demos = ['cpp', 'qt4', 'tex', 'ocaml', 'kde3', 'adv', 'cc', 'idl', 'docbook', 'xmlwaf', 'gnome'] zip_types = ['bz2', 'gz'] PRELUDE = '\timport waflib.extras.compat15' #from tokenize import * import tokenize import os, sys, re, io, optparse from waflib import Utils, Options, Logs from hashlib import md5 from waflib import Configure Configure.autoconfig = 1 def sub_file(fname, lst): f = open(fname, 'rU') txt = f.read() f.close() for (key, val) in lst: re_pat = re.compile(key, re.M) txt = re_pat.sub(val, txt) f = open(fname, 'w') f.write(txt) f.close() print("------> Executing code from the top-level wscript <-----") def init(ctx): if Options.options.setver: # maintainer only (ita) ver = Options.options.setver hexver = Utils.num2ver(ver) hexver = '0x%x'%hexver sub_file('wscript', (('^VERSION=(.*)', 'VERSION="%s"' % ver), )) sub_file('waf-light', (('^VERSION=(.*)', 'VERSION="%s"' % ver), )) pats = [] pats.append(('^WAFVERSION=(.*)', 'WAFVERSION="%s"' % ver)) pats.append(('^HEXVERSION(.*)', 'HEXVERSION=%s' % hexver)) try: #rev = k[0].cmd_and_log('git log | grep "^commit" | wc -l', quiet=0).strip() rev = k[0].cmd_and_log("git rev-parse HEAD").strip() pats.append(('^WAFREVISION(.*)', 'WAFREVISION="%s"' % rev)) except Exception: pass sub_file('waflib/Context.py', pats) sys.exit(0) def check(ctx): Logs.warn('Nothing to do') # this function is called before any other for parsing the command-line def options(opt): # generate waf opt.add_option('--make-waf', action='store_true', default=False, help='creates the waf script', dest='waf') opt.add_option('--zip-type', action='store', default='bz2', help='specify the zip type [Allowed values: %s]' % ' '.join(zip_types), dest='zip') opt.add_option('--make-batch', action='store_true', default=False, help='creates a convenience waf.bat file (done automatically on win32 systems)', dest='make_batch') opt.add_option('--yes', action='store_true', default=False, help=optparse.SUPPRESS_HELP, dest='yes') # those ones are not too interesting opt.add_option('--set-version', default='', help='sets the version number for waf releases (for the maintainer)', dest='setver') opt.add_option('--strip', action='store_true', default=True, help='shrinks waf (strip docstrings, saves 33kb)', dest='strip_comments') opt.add_option('--nostrip', action='store_false', help='no shrinking', dest='strip_comments') opt.add_option('--tools', action='store', help='Comma-separated 3rd party tools to add, eg: "compat,ocaml" [Default: "compat15"]', dest='add3rdparty', default='compat15') opt.add_option('--prelude', action='store', help='Code to execute before calling waf', dest='prelude', default=PRELUDE) opt.load('python') def compute_revision(): global REVISION def visit(arg, dirname, names): for pos, name in enumerate(names): if name[0] == '.' or name in ['_build_', 'build']: del names[pos] elif name.endswith('.py'): arg.append(os.path.join(dirname, name)) sources = [] os.path.walk('waflib', visit, sources) sources.sort() m = md5() for source in sources: f = file(source,'rb') readBytes = 100000 while (readBytes): readString = f.read(readBytes) m.update(readString) readBytes = len(readString) f.close() REVISION = m.hexdigest() def process_tokens(tokens): accu = [] prev = tokenize.NEWLINE indent = 0 line_buf = [] for (type, token, start, end, line) in tokens: token = token.replace('\r\n', '\n') if type == tokenize.NEWLINE: if line_buf: accu.append(indent * '\t') ln = "".join(line_buf) if ln == 'if __name__=="__main__":': break #ln = ln.replace('\n', '') accu.append(ln) accu.append('\n') line_buf = [] prev = tokenize.NEWLINE elif type == tokenize.INDENT: indent += 1 elif type == tokenize.DEDENT: indent -= 1 elif type == tokenize.NAME: if prev == tokenize.NAME or prev == tokenize.NUMBER: line_buf.append(' ') line_buf.append(token) elif type == tokenize.NUMBER: if prev == tokenize.NAME or prev == tokenize.NUMBER: line_buf.append(' ') line_buf.append(token) elif type == tokenize.STRING: if not line_buf and token.startswith('"'): pass else: line_buf.append(token) elif type == tokenize.COMMENT: pass elif type == tokenize.OP: line_buf.append(token) else: if token != "\n": line_buf.append(token) if token != '\n': prev = type body = "".join(accu) return body deco_re = re.compile('(def|class)\\s+(\w+)\\(.*') def process_decorators(body): lst = body.split('\n') accu = [] all_deco = [] buf = [] # put the decorator lines for line in lst: if line.startswith('@'): buf.append(line[1:]) elif buf: name = deco_re.sub('\\2', line) if not name: raise IOError("decorator not followed by a function!" + line) for x in buf: all_deco.append("%s(%s)" % (x, name)) accu.append(line) buf = [] else: accu.append(line) return "\n".join(accu+all_deco) def sfilter(path): if sys.version_info[0] >= 3 and Options.options.strip_comments: f = open(path, "rb") tk = tokenize.tokenize(f.readline) next(tk) # the first one is always tokenize.ENCODING for Python 3, ignore it cnt = process_tokens(tk) elif Options.options.strip_comments and path.endswith('.py'): f = open(path, "r") cnt = process_tokens(tokenize.generate_tokens(f.readline)) else: f = open(path, "r") cnt = f.read() f.close() if path.endswith('.py') : cnt = process_decorators(cnt) if cnt.find('set(') > -1: cnt = 'import sys\nif sys.hexversion < 0x020400f0: from sets import Set as set\n' + cnt cnt = '#! /usr/bin/env python\n# encoding: utf-8\n# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file\n\n' + cnt return (io.BytesIO(cnt.encode('utf-8')), len(cnt), cnt) def create_waf(*k, **kw): mw = 'tmp-waf-'+VERSION print("-> preparing %r" % mw) import tarfile, re zipType = Options.options.zip.strip().lower() if zipType not in zip_types: zipType = zip_types[0] #open a file as tar.[extension] for writing tar = tarfile.open('%s.tar.%s' % (mw, zipType), "w:%s" % zipType) files = [] add3rdparty = [] for x in Options.options.add3rdparty.split(','): if os.path.isabs(x): files.append(x) else: add3rdparty.append(x + '.py') for d in '. Tools extras'.split(): dd = os.path.join('waflib', d) for k in os.listdir(dd): if k == '__init__.py': files.append(os.path.join(dd, k)) continue if d == 'extras': if not k in add3rdparty: continue if k.endswith('.py'): files.append(os.path.join(dd, k)) for x in files: tarinfo = tar.gettarinfo(x, x) tarinfo.uid = tarinfo.gid = 0 tarinfo.uname = tarinfo.gname = 'root' (code, size, cnt) = sfilter(x) tarinfo.size = size if os.path.isabs(x): tarinfo.name = 'waflib/extras/' + os.path.split(x)[1] tar.addfile(tarinfo, code) tar.close() f = open('waf-light', 'rU') code1 = f.read() f.close() # now store the revision unique number in waf #compute_revision() #reg = re.compile('^REVISION=(.*)', re.M) #code1 = reg.sub(r'REVISION="%s"' % REVISION, code1) code1 = code1.replace("if sys.hexversion<0x206000f:\n\traise ImportError('Python >= 2.6 is required to create the waf file')\n", '') code1 = code1.replace('\timport waflib.extras.compat15#PRELUDE', Options.options.prelude) prefix = '' reg = re.compile('^INSTALL=(.*)', re.M) code1 = reg.sub(r'INSTALL=%r' % prefix, code1) #change the tarfile extension in the waf script reg = re.compile('bz2', re.M) code1 = reg.sub(zipType, code1) if zipType == 'gz': code1 = code1.replace('bunzip2', 'gzip -d') f = open('%s.tar.%s' % (mw, zipType), 'rb') cnt = f.read() f.close() # the REVISION value is the md5 sum of the binary blob (facilitate audits) m = md5() m.update(cnt) REVISION = m.hexdigest() reg = re.compile('^REVISION=(.*)', re.M) code1 = reg.sub(r'REVISION="%s"' % REVISION, code1) def find_unused(kd, ch): for i in range(35, 125): for j in range(35, 125): if i==j: continue if i == 39 or j == 39: continue if i == 92 or j == 92: continue s = chr(i) + chr(j) if -1 == kd.find(s.encode()): return (kd.replace(ch.encode(), s.encode()), s) raise # The reverse order prevent collisions (cnt, C2) = find_unused(cnt, '\r') (cnt, C1) = find_unused(cnt, '\n') f = open('waf', 'wb') ccc = code1.replace("C1='x'", "C1='%s'" % C1).replace("C2='x'", "C2='%s'" % C2) f.write(ccc.encode()) f.write(b'#==>\n#') f.write(cnt) f.write(b'\n#<==\n') f.close() if sys.platform == 'win32' or Options.options.make_batch: f = open('waf.bat', 'w') f.write('@python -x "%~dp0waf" %* & exit /b\n') f.close() if sys.platform != 'win32': os.chmod('waf', Utils.O755) os.unlink('%s.tar.%s' % (mw, zipType)) def make_copy(inf, outf): (a, b, cnt) = sfilter(inf) f = open(outf, "wb") f.write(cnt) f.close() def configure(conf): conf.load('python') conf.check_python_version((2,4)) def build(bld): waf = bld.path.make_node('waf') # create the node right here bld(name='create_waf', rule=create_waf, target=waf, always=True, color='PINK', update_outputs=True) #def dist(): # import Scripting # Scripting.g_dist_exts += ['Weak.py'] # shows how to exclude a file from dist # Scripting.Dist(APPNAME, VERSION) debian/waf-1.6/README0000664000000000000000000000245512145744415011144 0ustar WHAT YOU WILL FIND HERE ----------------------- Waf (1.6) For the manual: http://docs.waf.googlecode.com/git/book_16/single.html For the api docs: http://docs.waf.googlecode.com/git/apidocs_16/index.html For the examples: see the folder demos/ HOW TO CREATE THE WAF SCRIPT ---------------------------- Python 2.6, 2.7, 3.0 or 3.1 is required to generate the waf script. Execute: $ ./waf-light configure build Or, if you have several python versions installed: $ python3 ./waf-light configure build The Waf tools in waflib/extras are not added to the waf script. To add some of them, use the --tools switch: $ ./waf-light --tools=compat15,swig To add a tool that does not exist in the folder compat15, pass an absolute path To customize the initialization, pass the parameter 'prelude' $ ./waf-light --make-waf --tools=compat15,/comp/waf/aba.py --prelude=$'\tfrom waflib.extras import aba\n\taba.foo()' HOW TO TRY THE EXAMPLES ----------------------- Try this: $ cp waf demos/c/ $ cd demos/c/ $ ./waf configure build USING GIT --------- $ git clone https://code.google.com/p/waf/ set $HOME/.netrc to read: machine code.google.com login user@gmail.com password pass $ git remote add code https://code.google.com/p/waf.docs/ ... make a few changes $ git push code --------------------------- Thomas Nagy, 2011 (ita) debian/waf-1.6/waflib/0000775000000000000000000000000012253225220011506 5ustar debian/waf-1.6/waflib/Options.py0000664000000000000000000001711012145744415013527 0ustar #!/usr/bin/env python # encoding: utf-8 # Scott Newton, 2005 (scottn) # Thomas Nagy, 2006-2010 (ita) """ Support for waf command-line options Provides default command-line options, as well as custom ones, used by the ``options`` wscript function. """ import os, tempfile, optparse, sys, re from waflib import Logs, Utils, Context cmds = 'distclean configure build install clean uninstall check dist distcheck'.split() """ Constant representing the default waf commands displayed in:: $ waf --help """ options = {} """ A dictionary representing the command-line options:: $ waf --foo=bar """ commands = [] """ List of commands to execute extracted from the command-line. This list is consumed during the execution, see :py:func:`waflib.Scripting.run_commands`. """ lockfile = os.environ.get('WAFLOCK', '.lock-waf_%s_build' % sys.platform) try: cache_global = os.path.abspath(os.environ['WAFCACHE']) except KeyError: cache_global = '' platform = Utils.unversioned_sys_platform() class opt_parser(optparse.OptionParser): """ Command-line options parser. """ def __init__(self, ctx): optparse.OptionParser.__init__(self, conflict_handler="resolve", version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION)) self.formatter.width = Logs.get_term_cols() p = self.add_option self.ctx = ctx jobs = ctx.jobs() p('-j', '--jobs', dest='jobs', default=jobs, type='int', help='amount of parallel jobs (%r)' % jobs) p('-k', '--keep', dest='keep', default=0, action='count', help='keep running happily even if errors are found') p('-v', '--verbose', dest='verbose', default=0, action='count', help='verbosity level -v -vv or -vvv [default: 0]') p('--nocache', dest='nocache', default=False, action='store_true', help='ignore the WAFCACHE (if set)') p('--zones', dest='zones', default='', action='store', help='debugging zones (task_gen, deps, tasks, etc)') gr = optparse.OptionGroup(self, 'configure options') self.add_option_group(gr) gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') default_prefix = os.environ.get('PREFIX') if not default_prefix: if platform == 'win32': d = tempfile.gettempdir() default_prefix = d[0].upper() + d[1:] # win32 preserves the case, but gettempdir does not else: default_prefix = '/usr/local/' gr.add_option('--prefix', dest='prefix', default=default_prefix, help='installation prefix [default: %r]' % default_prefix) gr.add_option('--download', dest='download', default=False, action='store_true', help='try to download the tools if missing') gr = optparse.OptionGroup(self, 'build and install options') self.add_option_group(gr) gr.add_option('-p', '--progress', dest='progress_bar', default=0, action='count', help= '-p: progress bar; -pp: ide output') gr.add_option('--targets', dest='targets', default='', action='store', help='task generators, e.g. "target1,target2"') gr = optparse.OptionGroup(self, 'step options') self.add_option_group(gr) gr.add_option('--files', dest='files', default='', action='store', help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"') default_destdir = os.environ.get('DESTDIR', '') gr = optparse.OptionGroup(self, 'install/uninstall options') self.add_option_group(gr) gr.add_option('--destdir', help='installation root [default: %r]' % default_destdir, default=default_destdir, dest='destdir') gr.add_option('-f', '--force', dest='force', default=False, action='store_true', help='force file installation') def get_usage(self): """ Return the message to print on ``waf --help`` """ cmds_str = {} for cls in Context.classes: if not cls.cmd or cls.cmd == 'options': continue s = cls.__doc__ or '' cmds_str[cls.cmd] = s if Context.g_module: for (k, v) in Context.g_module.__dict__.items(): if k in ['options', 'init', 'shutdown']: continue if type(v) is type(Context.create_context): if v.__doc__ and not k.startswith('_'): cmds_str[k] = v.__doc__ just = 0 for k in cmds_str: just = max(just, len(k)) lst = [' %s: %s' % (k.ljust(just), v) for (k, v) in cmds_str.items()] lst.sort() ret = '\n'.join(lst) return '''waf [commands] [options] Main commands (example: ./waf build -j4) %s ''' % ret class OptionsContext(Context.Context): """ Collect custom options from wscript files and parses the command line. Set the global :py:const:`waflib.Options.commands` and :py:const:`waflib.Options.options` values. """ cmd = 'options' fun = 'options' def __init__(self, **kw): super(OptionsContext, self).__init__(**kw) self.parser = opt_parser(self) """Instance of :py:class:`waflib.Options.opt_parser`""" self.option_groups = {} def jobs(self): """ Find the amount of cpu cores to set the default amount of tasks executed in parallel. At runtime the options can be obtained from :py:const:`waflib.Options.options` :: from waflib.Options import options njobs = options.jobs :return: the amount of cpu cores :rtype: int """ count = int(os.environ.get('JOBS', 0)) if count < 1: if 'NUMBER_OF_PROCESSORS' in os.environ: # on Windows, use the NUMBER_OF_PROCESSORS environment variable count = int(os.environ.get('NUMBER_OF_PROCESSORS', 1)) else: # on everything else, first try the POSIX sysconf values if hasattr(os, 'sysconf_names'): if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_ONLN')) elif 'SC_NPROCESSORS_CONF' in os.sysconf_names: count = int(os.sysconf('SC_NPROCESSORS_CONF')) if not count and os.name not in ('nt', 'java'): try: tmp = self.cmd_and_log(['sysctl', '-n', 'hw.ncpu'], quiet=0) except Exception: pass else: if re.match('^[0-9]+$', tmp): count = int(tmp) if count < 1: count = 1 elif count > 1024: count = 1024 return count def add_option(self, *k, **kw): """ Wrapper for optparse.add_option:: def options(ctx): ctx.add_option('-u', '--use', dest='use', default=False, action='store_true', help='a boolean option') """ self.parser.add_option(*k, **kw) def add_option_group(self, *k, **kw): """ Wrapper for optparse.add_option_group:: def options(ctx): ctx.add_option_group('some options') gr.add_option('-u', '--use', dest='use', default=False, action='store_true') """ try: gr = self.option_groups[k[0]] except: gr = self.parser.add_option_group(*k, **kw) self.option_groups[k[0]] = gr return gr def get_option_group(self, opt_str): """ Wrapper for optparse.get_option_group:: def options(ctx): gr = ctx.get_option_group('configure options') gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') """ try: return self.option_groups[opt_str] except KeyError: for group in self.parser.option_groups: if group.title == opt_str: return group return None def parse_args(self, _args=None): """ Parse arguments from a list (not bound to the command-line). :param _args: arguments :type _args: list of strings """ global options, commands (options, leftover_args) = self.parser.parse_args(args=_args) commands = leftover_args if options.destdir: options.destdir = os.path.abspath(os.path.expanduser(options.destdir)) if options.verbose >= 1: self.load('errcheck') def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ super(OptionsContext, self).execute() self.parse_args() debian/waf-1.6/waflib/Task.py0000664000000000000000000010240112145744415012774 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Tasks represent atomic operations such as processes. """ import os, shutil, re, tempfile from waflib import Utils, Logs, Errors # task states NOT_RUN = 0 """The task was not executed yet""" MISSING = 1 """The task has been executed but the files have not been created""" CRASHED = 2 """The task execution returned a non-zero exit status""" EXCEPTION = 3 """An exception occured in the task execution""" SKIPPED = 8 """The task did not have to be executed""" SUCCESS = 9 """The task was successfully executed""" ASK_LATER = -1 """The task is not ready to be executed""" SKIP_ME = -2 """The task does not need to be executed""" RUN_ME = -3 """The task must be executed""" COMPILE_TEMPLATE_SHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld wd = getattr(tsk, 'cwd', None) p = env.get_flat tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s return tsk.exec_command(cmd, cwd=wd, env=env.env or None) ''' COMPILE_TEMPLATE_NOSHELL = ''' def f(tsk): env = tsk.env gen = tsk.generator bld = gen.bld wd = getattr(tsk, 'cwd', None) def to_list(xx): if isinstance(xx, str): return [xx] return xx tsk.last_cmd = lst = [] %s lst = [x for x in lst if x] return tsk.exec_command(lst, cwd=wd, env=env.env or None) ''' def cache_outputs(cls): """ Task class decorator applied to all task classes by default unless they define the attribute 'nocache':: from waflib import Task class foo(Task.Task): nocache = True If bld.cache_global is defined and if the task instances produces output nodes, the files will be copied into a folder in the cache directory The files may also be retrieved from that folder, if it exists """ m1 = cls.run def run(self): bld = self.generator.bld if bld.cache_global and not bld.nocache: if self.can_retrieve_cache(): return 0 return m1(self) cls.run = run m2 = cls.post_run def post_run(self): bld = self.generator.bld ret = m2(self) if bld.cache_global and not bld.nocache: self.put_files_cache() return ret cls.post_run = post_run return cls classes = {} "class tasks created by user scripts or Waf tools are kept in this dict name -> class object" class store_task_type(type): """ Metaclass: store the task types into :py:const:`waflib.Task.classes`. The attribute 'run_str' will be processed to compute a method 'run' on the task class The decorator :py:func:`waflib.Task.cache_outputs` is also applied to the class """ def __init__(cls, name, bases, dict): super(store_task_type, cls).__init__(name, bases, dict) name = cls.__name__ if name.endswith('_task'): name = name.replace('_task', '') if name != 'evil' and name != 'TaskBase': global classes if getattr(cls, 'run_str', None): # if a string is provided, convert it to a method (f, dvars) = compile_fun(cls.run_str, cls.shell) cls.hcode = cls.run_str cls.run_str = None cls.run = f cls.vars = list(set(cls.vars + dvars)) cls.vars.sort() elif getattr(cls, 'run', None) and not 'hcode' in cls.__dict__: # getattr(cls, 'hcode') would look in the upper classes cls.hcode = Utils.h_fun(cls.run) if not getattr(cls, 'nocache', None): cls = cache_outputs(cls) classes[name] = cls evil = store_task_type('evil', (object,), {}) "Base class provided to avoid writing a metaclass, so the code can run in python 2.6 and 3.x unmodified" class TaskBase(evil): """ Base class for all Waf tasks, which should be seen as an interface. For illustration purposes, instances of this class will execute the attribute 'fun' in :py:meth:`waflib.Task.TaskBase.run`. When in doubt, create subclasses of :py:class:`waflib.Task.Task` instead. Subclasses should override these methods: #. __str__: string to display to the user #. runnable_status: ask the task if it should be run, skipped, or if we have to ask later #. run: let threads execute the task #. post_run: let threads update the data regarding the task (cache) """ color = 'GREEN' """Color for the console display, see :py:const:`waflib.Logs.colors_lst`""" ext_in = [] """File extensions that objects of this task class might use""" ext_out = [] """File extensions that objects of this task class might create""" before = [] """List of task class names to execute before instances of this class""" after = [] """List of task class names to execute after instances of this class""" hcode = '' """String representing an additional hash for the class representation""" def __init__(self, *k, **kw): """ The base task class requires a task generator, which will be itself if missing """ self.hasrun = NOT_RUN try: self.generator = kw['generator'] except KeyError: self.generator = self def __repr__(self): "for debugging purposes" return '\n\t{task %r: %s %s}' % (self.__class__.__name__, id(self), str(getattr(self, 'fun', ''))) def __str__(self): "string to display to the user" if hasattr(self, 'fun'): return 'executing: %s\n' % self.fun.__name__ return self.__class__.__name__ + '\n' def __hash__(self): "Very fast hashing scheme but not persistent (replace/implement in subclasses and see :py:meth:`waflib.Task.Task.uid`)" return id(self) def exec_command(self, cmd, **kw): """ Wrapper for :py:meth:`waflib.Context.Context.exec_command` which sets a current working directory to ``build.variant_dir`` :return: the return code :rtype: int """ bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir return bld.exec_command(cmd, **kw) def runnable_status(self): """ State of the task :return: a task state in :py:const:`waflib.Task.RUN_ME`, :py:const:`waflib.Task.SKIP_ME` or :py:const:`waflib.Task.ASK_LATER`. :rtype: int """ return RUN_ME def process(self): """ Assume that the task has had a new attribute ``master`` which is an instance of :py:class:`waflib.Runner.Parallel`. Execute the task and then put it back in the queue :py:attr:`waflib.Runner.Parallel.out` (may be replaced by subclassing). """ m = self.master if m.stop: m.out.put(self) return # remove the task signature immediately before it is executed # in case of failure the task will be executed again try: del self.generator.bld.task_sigs[self.uid()] except: pass try: self.generator.bld.returned_tasks.append(self) self.log_display(self.generator.bld) ret = self.run() except Exception: self.err_msg = Utils.ex_stack() self.hasrun = EXCEPTION # TODO cleanup m.error_handler(self) m.out.put(self) return if ret: self.err_code = ret self.hasrun = CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = Utils.ex_stack() self.hasrun = EXCEPTION else: self.hasrun = SUCCESS if self.hasrun != SUCCESS: m.error_handler(self) m.out.put(self) def run(self): """ Called by threads to execute the tasks. The default is empty and meant to be overridden in subclasses. It is a bad idea to create nodes in this method (so, no node.ant_glob) :rtype: int """ if hasattr(self, 'fun'): return self.fun(self) return 0 def post_run(self): "Update the cache files (executed by threads). Override in subclasses." pass def log_display(self, bld): "Write the execution status on the context logger" bld.to_log(self.display()) def display(self): """ Return an execution status for the console, the progress bar, or the IDE output. :rtype: string """ col1 = Logs.colors(self.color) col2 = Logs.colors.NORMAL master = self.master def cur(): # the current task position, computed as late as possible tmp = -1 if hasattr(master, 'ready'): tmp -= master.ready.qsize() return master.processed + tmp if self.generator.bld.progress_bar == 1: return self.generator.bld.progress_line(cur(), master.total, col1, col2) if self.generator.bld.progress_bar == 2: ela = str(self.generator.bld.timer) try: ins = ','.join([n.name for n in self.inputs]) except AttributeError: ins = '' try: outs = ','.join([n.name for n in self.outputs]) except AttributeError: outs = '' return '|Total %s|Current %s|Inputs %s|Outputs %s|Time %s|\n' % (master.total, cur(), ins, outs, ela) s = str(self) if not s: return None total = master.total n = len(str(total)) fs = '[%%%dd/%%%dd] %%s%%s%%s' % (n, n) return fs % (cur(), total, col1, s, col2) def attr(self, att, default=None): """ Retrieve an attribute from the instance or from the class. :param att: variable name :type att: string :param default: default value """ ret = getattr(self, att, self) if ret is self: return getattr(self.__class__, att, default) return ret def hash_constraints(self): """ Identify a task type for all the constraints relevant for the scheduler: precedence, file production :return: a hash value :rtype: string """ cls = self.__class__ tup = (str(cls.before), str(cls.after), str(cls.ext_in), str(cls.ext_out), cls.__name__, cls.hcode) h = hash(tup) return h def format_error(self): """ Error message to display to the user when a build fails :rtype: string """ msg = getattr(self, 'last_cmd', '') name = getattr(self.generator, 'name', '') if getattr(self, "err_msg", None): return self.err_msg elif not self.hasrun: return 'task in %r was not executed for some reason: %r' % (name, self) elif self.hasrun == CRASHED: try: return ' -> task in %r failed (exit status %r): %r\n%r' % (name, self.err_code, self, msg) except AttributeError: return ' -> task in %r failed: %r\n%r' % (name, self, msg) elif self.hasrun == MISSING: return ' -> missing files in %r: %r\n%r' % (name, self, msg) else: return 'invalid status for task in %r: %r' % (name, self.hasrun) def colon(self, var1, var2): """ private function for the moment used for scriptlet expressions such as ${FOO_ST:FOO}, for example, if env.FOO_ST = ['-a', '-b'] env.FOO = ['1', '2'] then the result will be ['-a', '-b', '1', '-a', '-b', '2'] """ tmp = self.env[var1] if isinstance(var2, str): it = self.env[var2] else: it = var2 if isinstance(tmp, str): return [tmp % x for x in it] else: if Logs.verbose and not tmp and it: Logs.warn('Missing env variable %r for task %r (generator %r)' % (var1, self, self.generator)) lst = [] for y in it: lst.extend(tmp) lst.append(y) return lst class Task(TaskBase): """ This class deals with the filesystem (:py:class:`waflib.Node.Node`). The method :py:class:`waflib.Task.Task.runnable_status` uses a hash value (from :py:class:`waflib.Task.Task.signature`) which is persistent from build to build. When the value changes, the task has to be executed. The method :py:class:`waflib.Task.Task.post_run` will assign the task signature to the output nodes (if present). """ vars = [] """Variables to depend on (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" shell = False """Execute the command with the shell (class attribute)""" def __init__(self, *k, **kw): TaskBase.__init__(self, *k, **kw) self.env = kw['env'] """ConfigSet object (make sure to provide one)""" self.inputs = [] """List of input nodes, which represent the files used by the task instance""" self.outputs = [] """List of output nodes, which represent the files created by the task instance""" self.dep_nodes = [] """List of additional nodes to depend on""" self.run_after = set([]) """Set of tasks that must be executed before this one""" # Additionally, you may define the following #self.dep_vars = 'PREFIX DATADIR' def __str__(self): "string to display to the user" env = self.env src_str = ' '.join([a.nice_path(env) for a in self.inputs]) tgt_str = ' '.join([a.nice_path(env) for a in self.outputs]) if self.outputs: sep = ' -> ' else: sep = '' return '%s: %s%s%s\n' % (self.__class__.__name__.replace('_task', ''), src_str, sep, tgt_str) def __repr__(self): "for debugging purposes" return "".join(['\n\t{task %r: ' % id(self), self.__class__.__name__, " ", ",".join([x.name for x in self.inputs]), " -> ", ",".join([x.name for x in self.outputs]), '}']) def uid(self): """ Return an identifier used to determine if tasks are up-to-date. Since the identifier will be stored between executions, it must be: - unique: no two tasks return the same value (for a given build context) - the same for a given task instance By default, the node paths, the class name, and the function are used as inputs to compute a hash. The pointer to the object (python built-in 'id') will change between build executions, and must be avoided in such hashes. :return: hash value :rtype: string """ try: return self.uid_ except AttributeError: # this is not a real hot zone, but we want to avoid surprizes here m = Utils.md5() up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.abspath().encode()) self.uid_ = m.digest() return self.uid_ def set_inputs(self, inp): """ Append the nodes to the *inputs* :param inp: input nodes :type inp: node or list of nodes """ if isinstance(inp, list): self.inputs += inp else: self.inputs.append(inp) def set_outputs(self, out): """ Append the nodes to the *outputs* :param out: output nodes :type out: node or list of nodes """ if isinstance(out, list): self.outputs += out else: self.outputs.append(out) def set_run_after(self, task): """ Run this task only after *task*. Affect :py:meth:`waflib.Task.runnable_status` :param task: task :type task: :py:class:`waflib.Task.Task` """ # TODO: handle lists too? assert isinstance(task, TaskBase) self.run_after.add(task) def signature(self): """ Task signatures are stored between build executions, they are use to track the changes made to the input nodes (not to the outputs!). The signature hashes data from various sources: * explicit dependencies: files listed in the inputs (list of node objects) :py:meth:`waflib.Task.Task.sig_explicit_deps` * implicit dependencies: list of nodes returned by scanner methods (when present) :py:meth:`waflib.Task.Task.sig_implicit_deps` * hashed data: variables/values read from task.__class__.vars/task.env :py:meth:`waflib.Task.Task.sig_vars` If the signature is expected to give a different result, clear the cache kept in ``self.cache_sig``:: from waflib import Task class cls(Task.Task): def signature(self): sig = super(Task.Task, self).signature() delattr(self, 'cache_sig') return super(Task.Task, self).signature() """ try: return self.cache_sig except AttributeError: pass self.m = Utils.md5() self.m.update(self.hcode.encode()) # explicit deps self.sig_explicit_deps() # env vars self.sig_vars() # implicit deps / scanner results if self.scan: try: self.sig_implicit_deps() except Errors.TaskRescan: return self.signature() ret = self.cache_sig = self.m.digest() return ret def runnable_status(self): """ Override :py:meth:`waflib.Task.TaskBase.runnable_status` to determine if the task is ready to be run (:py:attr:`waflib.Task.Task.run_after`) """ #return 0 # benchmarking for t in self.run_after: if not t.hasrun: return ASK_LATER bld = self.generator.bld # first compute the signature try: new_sig = self.signature() except Errors.TaskNotReady: return ASK_LATER # compare the signature to a signature computed previously key = self.uid() try: prev_sig = bld.task_sigs[key] except KeyError: Logs.debug("task: task %r must run as it was never run before or the task code changed" % self) return RUN_ME # compare the signatures of the outputs for node in self.outputs: try: if node.sig != new_sig: return RUN_ME except AttributeError: Logs.debug("task: task %r must run as the output nodes do not exist" % self) return RUN_ME if new_sig != prev_sig: return RUN_ME return SKIP_ME def post_run(self): """ Called after successful execution to update the cache data :py:class:`waflib.Node.Node` sigs and :py:attr:`waflib.Build.BuildContext.task_sigs`. The node signature is obtained from the task signature, but the output nodes may also get the signature of their contents. See the class decorator :py:func:`waflib.Task.update_outputs` if you need this behaviour. """ bld = self.generator.bld sig = self.signature() for node in self.outputs: # check if the node exists .. try: os.stat(node.abspath()) except OSError: self.hasrun = MISSING self.err_msg = '-> missing file: %r' % node.abspath() raise Errors.WafError(self.err_msg) # important, store the signature for the next run node.sig = sig bld.task_sigs[self.uid()] = self.cache_sig def sig_explicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature`, hash :py:attr:`waflib.Task.Task.inputs` and :py:attr:`waflib.Task.Task.dep_nodes` signatures. :rtype: hash value """ bld = self.generator.bld upd = self.m.update # the inputs for x in self.inputs + self.dep_nodes: try: upd(x.get_bld_sig()) except (AttributeError, TypeError): raise Errors.WafError('Missing node signature for %r (required by %r)' % (x, self)) # manual dependencies, they can slow down the builds if bld.deps_man: additional_deps = bld.deps_man for x in self.inputs + self.outputs: try: d = additional_deps[id(x)] except KeyError: continue for v in d: if isinstance(v, bld.root.__class__): try: v = v.get_bld_sig() except AttributeError: raise Errors.WafError('Missing node signature for %r (required by %r)' % (v, self)) elif hasattr(v, '__call__'): v = v() # dependency is a function, call it upd(v) return self.m.digest() def sig_vars(self): """ Used by :py:meth:`waflib.Task.Task.signature`, hash :py:attr:`waflib.Task.Task.env` variables/values :rtype: hash value """ bld = self.generator.bld env = self.env upd = self.m.update # dependencies on the environment vars act_sig = bld.hash_env_vars(env, self.__class__.vars) upd(act_sig) # additional variable dependencies, if provided dep_vars = getattr(self, 'dep_vars', None) if dep_vars: upd(bld.hash_env_vars(env, dep_vars)) return self.m.digest() scan = None """ This method, when provided, returns a tuple containing: * a list of nodes corresponding to real files * a list of names for files not found in path_lst For example:: from waflib.Task import Task class mytask(Task): def scan(self, node): return ((), ()) The first and second lists are stored in :py:attr:`waflib.Build.BuildContext.node_deps` and :py:attr:`waflib.Build.BuildContext.raw_deps` respectively. """ def sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.signature` hashes node signatures obtained by scanning for dependencies (:py:meth:`waflib.Task.Task.scan`). The exception :py:class:`waflib.Errors.TaskRescan` is thrown when a file has changed. When this occurs, :py:meth:`waflib.Task.Task.signature` is called once again, and this method will be executed once again, this time calling :py:meth:`waflib.Task.Task.scan` for searching the dependencies. :rtype: hash value """ bld = self.generator.bld # get the task signatures from previous runs key = self.uid() prev = bld.task_sigs.get((key, 'imp'), []) # for issue #379 if prev: try: if prev == self.compute_sig_implicit_deps(): return prev except: # when a file was renamed (IOError usually), remove the stale nodes (headers in folders without source files) # this will break the order calculation for headers created during the build in the source directory (should be uncommon) # the behaviour will differ when top != out for x in bld.node_deps.get(self.uid(), []): if x.is_child_of(bld.srcnode): try: os.stat(x.abspath()) except: try: del x.parent.children[x.name] except: pass del bld.task_sigs[(key, 'imp')] raise Errors.TaskRescan('rescan') # no previous run or the signature of the dependencies has changed, rescan the dependencies (nodes, names) = self.scan() if Logs.verbose: Logs.debug('deps: scanner for %s returned %s %s' % (str(self), str(nodes), str(names))) # store the dependencies in the cache bld.node_deps[key] = nodes bld.raw_deps[key] = names # might happen self.are_implicit_nodes_ready() # recompute the signature and return it try: bld.task_sigs[(key, 'imp')] = sig = self.compute_sig_implicit_deps() except: if Logs.verbose: for k in bld.node_deps.get(self.uid(), []): try: k.get_bld_sig() except: Logs.warn('Missing signature for node %r (may cause rebuilds)' % k) else: return sig def compute_sig_implicit_deps(self): """ Used by :py:meth:`waflib.Task.Task.sig_implicit_deps` for computing the actual hash of the :py:class:`waflib.Node.Node` returned by the scanner. :return: hash value :rtype: string """ upd = self.m.update bld = self.generator.bld self.are_implicit_nodes_ready() # scanner returns a node that does not have a signature # just *ignore* the error and let them figure out from the compiler output # waf -k behaviour for k in bld.node_deps.get(self.uid(), []): upd(k.get_bld_sig()) return self.m.digest() def are_implicit_nodes_ready(self): """ For each node returned by the scanner, see if there is a task behind it, and force the build order The performance impact on null builds is nearly invisible (1.66s->1.86s), but this is due to agressive caching (1.86s->28s) """ bld = self.generator.bld try: cache = bld.dct_implicit_nodes except: bld.dct_implicit_nodes = cache = {} try: dct = cache[bld.cur] except KeyError: dct = cache[bld.cur] = {} for tsk in bld.cur_tasks: for x in tsk.outputs: dct[x] = tsk modified = False for x in bld.node_deps.get(self.uid(), []): if x in dct: self.run_after.add(dct[x]) modified = True if modified: for tsk in self.run_after: if not tsk.hasrun: #print "task is not ready..." raise Errors.TaskNotReady('not ready') def can_retrieve_cache(self): """ Used by :py:meth:`waflib.Task.cache_outputs` Retrieve build nodes from the cache update the file timestamps to help cleaning the least used entries from the cache additionally, set an attribute 'cached' to avoid re-creating the same cache files Suppose there are files in `cache/dir1/file1` and `cache/dir2/file2`: #. read the timestamp of dir1 #. try to copy the files #. look at the timestamp again, if it has changed, the data may have been corrupt (cache update by another process) #. should an exception occur, ignore the data """ if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) # first try to access the cache folder for the task dname = os.path.join(self.generator.bld.cache_global, ssig) try: t1 = os.stat(dname).st_mtime except OSError: return None for node in self.outputs: orig = os.path.join(dname, node.name) try: shutil.copy2(orig, node.abspath()) # mark the cache file as used recently (modified) os.utime(orig, None) except (OSError, IOError): Logs.debug('task: failed retrieving file') return None # is it the same folder? try: t2 = os.stat(dname).st_mtime except OSError: return None if t1 != t2: return None for node in self.outputs: node.sig = sig if self.generator.bld.progress_bar < 1: self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True def put_files_cache(self): """ Used by :py:func:`waflib.Task.cache_outputs` to store the build files in the cache """ # file caching, if possible # try to avoid data corruption as much as possible if getattr(self, 'cached', None): return None if not getattr(self, 'outputs', None): return None sig = self.signature() ssig = Utils.to_hex(self.uid()) + Utils.to_hex(sig) dname = os.path.join(self.generator.bld.cache_global, ssig) tmpdir = tempfile.mkdtemp(prefix=self.generator.bld.cache_global + os.sep + 'waf') try: shutil.rmtree(dname) except: pass try: for node in self.outputs: dest = os.path.join(tmpdir, node.name) shutil.copy2(node.abspath(), dest) except (OSError, IOError): try: shutil.rmtree(tmpdir) except: pass else: try: os.rename(tmpdir, dname) except OSError: try: shutil.rmtree(tmpdir) except: pass else: try: os.chmod(dname, Utils.O755) except: pass def is_before(t1, t2): """ Return a non-zero value if task t1 is to be executed before task t2:: t1.ext_out = '.h' t2.ext_in = '.h' t2.after = ['t1'] t1.before = ['t2'] waflib.Task.is_before(t1, t2) # True :param t1: task :type t1: :py:class:`waflib.Task.TaskBase` :param t2: task :type t2: :py:class:`waflib.Task.TaskBase` """ to_list = Utils.to_list for k in to_list(t2.ext_in): if k in to_list(t1.ext_out): return 1 if t1.__class__.__name__ in to_list(t2.after): return 1 if t2.__class__.__name__ in to_list(t1.before): return 1 return 0 def set_file_constraints(tasks): """ Adds tasks to the task 'run_after' attribute based on the task inputs and outputs :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.TaskBase` """ ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) for x in tasks: for a in getattr(x, 'inputs', []) + getattr(x, 'dep_nodes', []): ins[id(a)].add(x) for a in getattr(x, 'outputs', []): outs[id(a)].add(x) links = set(ins.keys()).intersection(outs.keys()) for k in links: for a in ins[k]: a.run_after.update(outs[k]) def set_precedence_constraints(tasks): """ Add tasks to the task 'run_after' attribute based on the after/before/ext_out/ext_in attributes :param tasks: tasks :type tasks: list of :py:class:`waflib.Task.TaskBase` """ cstr_groups = Utils.defaultdict(list) for x in tasks: h = x.hash_constraints() cstr_groups[h].append(x) keys = list(cstr_groups.keys()) maxi = len(keys) # this list should be short for i in range(maxi): t1 = cstr_groups[keys[i]][0] for j in range(i + 1, maxi): t2 = cstr_groups[keys[j]][0] # add the constraints based on the comparisons if is_before(t1, t2): a = i b = j elif is_before(t2, t1): a = j b = i else: continue for x in cstr_groups[keys[b]]: x.run_after.update(cstr_groups[keys[a]]) def funex(c): """ Compile a function by 'exec' :param c: function to compile :type c: string :return: the function 'f' declared in the input string :rtype: function """ dc = {} exec(c, dc) return dc['f'] reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})", re.M) def compile_fun_shell(line): """ Create a compiled function to execute a process with the shell WARNING: this method may disappear anytime, so use compile_fun instead """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return '\\\\' elif g('subst'): extr.append((g('var'), g('code'))); return "%s" return None line = reg_act.sub(repl, line) or line parm = [] dvars = [] app = parm.append for (var, meth) in extr: if var == 'SRC': if meth: app('tsk.inputs%s' % meth) else: app('" ".join([a.path_from(bld.bldnode) for a in tsk.inputs])') elif var == 'TGT': if meth: app('tsk.outputs%s' % meth) else: app('" ".join([a.path_from(bld.bldnode) for a in tsk.outputs])') elif meth: if meth.startswith(':'): m = meth[1:] if m == 'SRC': m = '[a.path_from(bld.bldnode) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(bld.bldnode) for a in tsk.outputs]' elif m[:3] not in ('tsk', 'gen', 'bld'): dvars.extend([var, meth[1:]]) m = '%r' % m app('" ".join(tsk.colon(%r, %s))' % (var, m)) else: app('%s%s' % (var, meth)) else: if not var in dvars: dvars.append(var) app("p('%s')" % var) if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) else: parm = '' c = COMPILE_TEMPLATE_SHELL % (line, parm) Logs.debug('action: %s' % c) return (funex(c), dvars) def compile_fun_noshell(line): """ Create a compiled function to execute a process without the shell WARNING: this method may disappear anytime, so use compile_fun instead """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('subst'): extr.append((g('var'), g('code'))); return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) buf = [] dvars = [] app = buf.append for x in range(len(extr)): params[x] = params[x].strip() if params[x]: app("lst.extend(%r)" % params[x].split()) (var, meth) = extr[x] if var == 'SRC': if meth: app('lst.append(tsk.inputs%s)' % meth) else: app("lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs])") elif var == 'TGT': if meth: app('lst.append(tsk.outputs%s)' % meth) else: app("lst.extend([a.path_from(bld.bldnode) for a in tsk.outputs])") elif meth: if meth.startswith(':'): m = meth[1:] if m == 'SRC': m = '[a.path_from(bld.bldnode) for a in tsk.inputs]' elif m == 'TGT': m = '[a.path_from(bld.bldnode) for a in tsk.outputs]' elif m[:3] not in ('tsk', 'gen', 'bld'): dvars.extend([var, m]) m = '%r' % m app('lst.extend(tsk.colon(%r, %s))' % (var, m)) else: app('lst.extend(gen.to_list(%s%s))' % (var, meth)) else: app('lst.extend(to_list(env[%r]))' % var) if not var in dvars: dvars.append(var) if extr: if params[-1]: app("lst.extend(%r)" % params[-1].split()) fun = COMPILE_TEMPLATE_NOSHELL % "\n\t".join(buf) Logs.debug('action: %s' % fun) return (funex(fun), dvars) def compile_fun(line, shell=False): """ Parse a string expression such as "${CC} ${SRC} -o ${TGT}" and return a pair containing: * the function created (compiled) for use as :py:meth:`waflib.Task.TaskBase.run` * the list of variables that imply a dependency from self.env for example:: from waflib.Task import compile_fun compile_fun('cxx', '${CXX} -o ${TGT[0]} ${SRC} -I ${SRC[0].parent.bldpath()}') def build(bld): bld(source='wscript', rule='echo "foo\\${SRC[0].name}\\bar"') The env variables (CXX, ..) on the task must not hold dicts (order) The reserved keywords *TGT* and *SRC* represent the task input and output nodes """ if line.find('<') > 0 or line.find('>') > 0 or line.find('&&') > 0: shell = True if shell: return compile_fun_shell(line) else: return compile_fun_noshell(line) def task_factory(name, func=None, vars=None, color='GREEN', ext_in=[], ext_out=[], before=[], after=[], shell=False, scan=None): """ Return a new task subclass with the function ``run`` compiled from the line given. Provided for compatibility with waf 1.4-1.5, when we did not use metaclasses to register new objects. :param func: method run :type func: string or function :param vars: list of variables to hash :type vars: list of string :param color: color to use :type color: string :param shell: when *func* is a string, enable/disable the use of the shell :type shell: bool :param scan: method scan :type scan: function :rtype: :py:class:`waflib.Task.Task` """ params = { 'vars': vars or [], # function arguments are static, and this one may be modified by the class 'color': color, 'name': name, 'ext_in': Utils.to_list(ext_in), 'ext_out': Utils.to_list(ext_out), 'before': Utils.to_list(before), 'after': Utils.to_list(after), 'shell': shell, 'scan': scan, } if isinstance(func, str): params['run_str'] = func else: params['run'] = func cls = type(Task)(name, (Task,), params) global classes classes[name] = cls return cls def always_run(cls): """ Task class decorator Set all task instances of this class to be executed whenever a build is started The task signature is calculated, but the result of the comparation between task signatures is bypassed """ old = cls.runnable_status def always(self): ret = old(self) if ret == SKIP_ME: ret = RUN_ME return ret cls.runnable_status = always return cls def update_outputs(cls): """ Task class decorator If you want to create files in the source directory. For example, to keep *foo.txt* in the source directory, create it first and declare:: def build(bld): bld(rule='cp ${SRC} ${TGT}', source='wscript', target='foo.txt', update_outputs=True) """ old_post_run = cls.post_run def post_run(self): old_post_run(self) for node in self.outputs: node.sig = Utils.h_file(node.abspath()) self.generator.bld.task_sigs[node.abspath()] = self.uid() # issue #1017 cls.post_run = post_run old_runnable_status = cls.runnable_status def runnable_status(self): status = old_runnable_status(self) if status != RUN_ME: return status try: # by default, we check that the output nodes have the signature of the task # perform a second check, returning 'SKIP_ME' as we are expecting that # the signatures do not match bld = self.generator.bld prev_sig = bld.task_sigs[self.uid()] if prev_sig == self.signature(): for x in self.outputs: if not x.sig or bld.task_sigs[x.abspath()] != self.uid(): return RUN_ME return SKIP_ME except KeyError: pass except IndexError: pass except AttributeError: pass return RUN_ME cls.runnable_status = runnable_status return cls debian/waf-1.6/waflib/fixpy2.py0000664000000000000000000000246412145744415013323 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ burn a book, save a tree """ import os all_modifs = {} def fixdir(dir): """call all the substitution functions on the waf folders""" global all_modifs for k in all_modifs: for v in all_modifs[k]: modif(os.path.join(dir, 'waflib'), k, v) def modif(dir, name, fun): """execute a substitution function""" if name == '*': lst = [] for y in '. Tools extras'.split(): for x in os.listdir(os.path.join(dir, y)): if x.endswith('.py'): lst.append(y + os.sep + x) for x in lst: modif(dir, x, fun) return filename = os.path.join(dir, name) f = open(filename, 'r') txt = f.read() f.close() txt = fun(txt) f = open(filename, 'w') f.write(txt) f.close() def subst(*k): """register a substitution function""" def do_subst(fun): global all_modifs for x in k: try: all_modifs[x].append(fun) except KeyError: all_modifs[x] = [fun] return fun return do_subst @subst('*') def r1(code): "utf-8 fixes for python < 2.6" code = code.replace('as e:', ',e:') code = code.replace(".decode(sys.stdout.encoding or 'iso8859-1')", '') code = code.replace('.encode()', '') return code @subst('Runner.py') def r4(code): "generator syntax" code = code.replace('next(self.biter)', 'self.biter.next()') return code debian/waf-1.6/waflib/Errors.py0000664000000000000000000000321312145744415013347 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Exceptions used in the Waf code """ import traceback, sys class WafError(Exception): """Base class for all Waf errors""" def __init__(self, msg='', ex=None): """ :param msg: error message :type msg: string :param ex: exception causing this error (optional) :type ex: exception """ self.msg = msg assert not isinstance(msg, Exception) self.stack = [] if ex: if not msg: self.msg = str(ex) if isinstance(ex, WafError): self.stack = ex.stack else: self.stack = traceback.extract_tb(sys.exc_info()[2]) self.stack += traceback.extract_stack()[:-1] self.verbose_msg = ''.join(traceback.format_list(self.stack)) def __str__(self): return str(self.msg) class BuildError(WafError): """ Errors raised during the build and install phases """ def __init__(self, error_tasks=[]): """ :param error_tasks: tasks that could not complete normally :type error_tasks: list of task objects """ self.tasks = error_tasks WafError.__init__(self, self.format_error()) def format_error(self): """format the error messages from the tasks that failed""" lst = ['Build failed'] for tsk in self.tasks: txt = tsk.format_error() if txt: lst.append(txt) return '\n'.join(lst) class ConfigurationError(WafError): """ Configuration exception raised in particular by :py:meth:`waflib.Context.Context.fatal` """ pass class TaskRescan(WafError): """task-specific exception type, trigger a signature recomputation""" pass class TaskNotReady(WafError): """task-specific exception type, raised when the task signature cannot be computed""" pass debian/waf-1.6/waflib/Node.py0000664000000000000000000004726112145744415012773 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Node: filesystem structure, contains lists of nodes #. Each file/folder is represented by exactly one node. #. Some potential class properties are stored on :py:class:`waflib.Build.BuildContext` : nodes to depend on, etc. Unused class members can increase the `.wafpickle` file size sensibly. #. Node objects should never be created directly, use the methods :py:func:`Node.make_node` or :py:func:`Node.find_node` #. The methods :py:func:`Node.find_resource`, :py:func:`Node.find_dir` :py:func:`Node.find_or_declare` should be used when a build context is present #. Each instance of :py:class:`waflib.Context.Context` has a unique :py:class:`Node` subclass. (:py:class:`waflib.Node.Nod3`, see the :py:class:`waflib.Context.Context` initializer). A reference to the context owning a node is held as self.ctx """ import os, re, sys, shutil from waflib import Utils, Errors exclude_regs = ''' **/*~ **/#*# **/.#* **/%*% **/._* **/CVS **/CVS/** **/.cvsignore **/SCCS **/SCCS/** **/vssver.scc **/.svn **/.svn/** **/BitKeeper **/.git **/.git/** **/.gitignore **/.bzr **/.bzrignore **/.bzr/** **/.hg **/.hg/** **/_MTN **/_MTN/** **/.arch-ids **/{arch} **/_darcs **/_darcs/** **/.DS_Store''' """ Ant patterns for files and folders to exclude while doing the recursive traversal in :py:meth:`waflib.Node.Node.ant_glob` """ # TODO optimize split_path by performing a replacement when unpacking? def split_path(path): """ Split a path by os.sep (This is not os.path.split) :param path: path to split :type path: string :rtype: list of string :return: the path, split """ return path.split('/') def split_path_cygwin(path): if path.startswith('//'): ret = path.split('/')[2:] ret[0] = '/' + ret[0] return ret return path.split('/') re_sp = re.compile('[/\\\\]') def split_path_win32(path): if path.startswith('\\\\'): ret = re.split(re_sp, path)[2:] ret[0] = '\\' + ret[0] return ret return re.split(re_sp, path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif Utils.is_win32: split_path = split_path_win32 class Node(object): """ This class is organized in two parts * The basic methods meant for filesystem access (compute paths, create folders, etc) * The methods bound to a :py:class:`waflib.Build.BuildContext` (require ``bld.srcnode`` and ``bld.bldnode``) The Node objects are not thread safe in any way. """ __slots__ = ('name', 'sig', 'children', 'parent', 'cache_abspath', 'cache_isdir') def __init__(self, name, parent): self.name = name self.parent = parent if parent: if name in parent.children: raise Errors.WafError('node %s exists in the parent files %r already' % (name, parent)) parent.children[name] = self def __setstate__(self, data): "Deserializes from data" self.name = data[0] self.parent = data[1] if data[2] is not None: self.children = data[2] if data[3] is not None: self.sig = data[3] def __getstate__(self): "Serialize the node info" return (self.name, self.parent, getattr(self, 'children', None), getattr(self, 'sig', None)) def __str__(self): "String representation (name), for debugging purposes" return self.name def __repr__(self): "String representation (abspath), for debugging purposes" return self.abspath() def __hash__(self): "Node hash, used for storage in dicts. This hash is not persistent." return id(self) def __eq__(self, node): "Node comparison, based on the IDs" return id(self) == id(node) def __copy__(self): "Implemented to prevent nodes from being copied (raises an exception)" raise Errors.WafError('nodes are not supposed to be copied') def read(self, flags='r'): """ Return the contents of the file represented by this node:: def build(bld): bld.path.find_node('wscript').read() :type fname: string :param fname: Path to file :type m: string :param m: Open mode :rtype: string :return: File contents """ return Utils.readf(self.abspath(), flags) def write(self, data, flags='w'): """ Write some text to the physical file represented by this node:: def build(bld): bld.path.make_node('foo.txt').write('Hello, world!') :type data: string :param data: data to write :type flags: string :param flags: Write mode """ f = None try: f = open(self.abspath(), flags) f.write(data) finally: if f: f.close() def chmod(self, val): """ Change file/dir permissions:: def build(bld): bld.path.chmod(493) # 0755 """ os.chmod(self.abspath(), val) def delete(self): """Delete the file/folder physically (but not the node)""" try: if getattr(self, 'children', None): shutil.rmtree(self.abspath()) else: os.unlink(self.abspath()) except: pass try: delattr(self, 'children') except: pass def suffix(self): """Return the file extension""" k = max(0, self.name.rfind('.')) return self.name[k:] def height(self): """Depth in the folder hierarchy from the filesystem root or from all the file drives""" d = self val = -1 while d: d = d.parent val += 1 return val def listdir(self): """List the folder contents""" lst = Utils.listdir(self.abspath()) lst.sort() return lst def mkdir(self): """ Create a folder represented by this node, creating intermediate nodes as needed An exception will be raised only when the folder cannot possibly exist there """ if getattr(self, 'cache_isdir', None): return try: self.parent.mkdir() except: pass if self.name: try: os.makedirs(self.abspath()) except OSError: pass if not os.path.isdir(self.abspath()): raise Errors.WafError('Could not create the directory %s' % self.abspath()) try: self.children except: self.children = {} self.cache_isdir = True def find_node(self, lst): """ Find a node on the file system (files or folders), create intermediate nodes as needed :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur continue try: if x in cur.children: cur = cur.children[x] continue except: cur.children = {} # optimistic: create the node first then look if it was correct to do so cur = self.__class__(x, cur) try: os.stat(cur.abspath()) except: del cur.parent.children[x] return None ret = cur try: os.stat(ret.abspath()) except: del ret.parent.children[ret.name] return None try: while not getattr(cur.parent, 'cache_isdir', None): cur = cur.parent cur.cache_isdir = True except AttributeError: pass return ret def make_node(self, lst): """ Find or create a node without looking on the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self for x in lst: if x == '..': cur = cur.parent or cur continue if getattr(cur, 'children', {}): if x in cur.children: cur = cur.children[x] continue else: cur.children = {} cur = self.__class__(x, cur) return cur def search(self, lst): """ Search for a node without looking on the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] cur = self try: for x in lst: if x == '..': cur = cur.parent or cur else: cur = cur.children[x] return cur except: pass def path_from(self, node): """ Path of this node seen from the other:: def build(bld): n1 = bld.path.find_node('foo/bar/xyz.txt') n2 = bld.path.find_node('foo/stuff/') n1.path_from(n2) # './bar/xyz.txt' :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` """ c1 = self c2 = node c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while id(c1) != id(c2): lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent for i in range(up): lst.append('..') lst.reverse() return os.sep.join(lst) or '.' def abspath(self): """ Absolute path. A cache is kept in the context as ``cache_node_abspath`` """ try: return self.cache_abspath except: pass # think twice before touching this (performance + complexity + correctness) if os.sep == '/': if not self.parent: val = os.sep elif not self.parent.name: val = os.sep + self.name else: val = self.parent.abspath() + os.sep + self.name else: if not self.parent: val = '' elif not self.parent.name: val = self.name + os.sep else: val = self.parent.abspath().rstrip(os.sep) + os.sep + self.name self.cache_abspath = val return val def is_child_of(self, node): """ Does this node belong to the subtree node?:: def build(bld): node = bld.path.find_node('wscript') node.is_child_of(bld.path) # True :param node: path to use as a reference :type node: :py:class:`waflib.Node.Node` """ p = self diff = self.height() - node.height() while diff > 0: diff -= 1 p = p.parent return id(p) == id(node) def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True): """ Semi-private and recursive method used by ant_glob. :param accept: function used for accepting/rejecting a node, returns the patterns that can be still accepted in recursion :type accept: function :param maxdepth: maximum depth in the filesystem (25) :type maxdepth: int :param pats: list of patterns to accept and list of patterns to exclude :type pats: tuple :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool """ dircont = self.listdir() dircont.sort() try: lst = set(self.children.keys()) if remove: for x in lst - set(dircont): del self.children[x] except: self.children = {} for name in dircont: npats = accept(name, pats) if npats and npats[0]: accepted = [] in npats[0] node = self.make_node([name]) isdir = os.path.isdir(node.abspath()) if accepted: if isdir: if dir: yield node else: if src: yield node if getattr(node, 'cache_isdir', None) or isdir: node.cache_isdir = True if maxdepth: for k in node.ant_iter(accept=accept, maxdepth=maxdepth - 1, pats=npats, dir=dir, src=src, remove=remove): yield k raise StopIteration def ant_glob(self, *k, **kw): """ This method is used for finding files across folders. It behaves like ant patterns: * ``**/*`` find all files recursively * ``**/*.class`` find all files ending by .class * ``..`` find files having two dot characters For example:: def configure(cfg): cfg.path.ant_glob('**/*.cpp') # find all .cpp files cfg.root.ant_glob('etc/*.txt') # using the filesystem root can be slow cfg.path.ant_glob('*.cpp', excl=['*.c'], src=True, dir=False) For more information see http://ant.apache.org/manual/dirtasks.html The nodes that correspond to files and folders that do not exist will be removed. To prevent this behaviour, pass 'remove=False' :param incl: ant patterns or list of patterns to include :type incl: string or list of strings :param excl: ant patterns or list of patterns to exclude :type excl: string or list of strings :param dir: return folders too (False by default) :type dir: bool :param src: return files (True by default) :type src: bool :param remove: remove files/folders that do not exist (True by default) :type remove: bool :param maxdepth: maximum depth of recursion :type maxdepth: int """ src = kw.get('src', True) dir = kw.get('dir', False) excl = kw.get('excl', exclude_regs) incl = k and k[0] or kw.get('incl', '**') def to_pat(s): lst = Utils.to_list(s) ret = [] for x in lst: x = x.replace('\\', '/').replace('//', '/') if x.endswith('/'): x += '**' lst2 = x.split('/') accu = [] for k in lst2: if k == '**': accu.append(k) else: k = k.replace('.', '[.]').replace('*','.*').replace('?', '.').replace('+', '\\+') k = '^%s$' % k try: #print "pattern", k accu.append(re.compile(k)) except Exception as e: raise Errors.WafError("Invalid pattern: %s" % k, e) ret.append(accu) return ret def filtre(name, nn): ret = [] for lst in nn: if not lst: pass elif lst[0] == '**': ret.append(lst) if len(lst) > 1: if lst[1].match(name): ret.append(lst[2:]) else: ret.append([]) elif lst[0].match(name): ret.append(lst[1:]) return ret def accept(name, pats): nacc = filtre(name, pats[0]) nrej = filtre(name, pats[1]) if [] in nrej: nacc = [] return [nacc, nrej] ret = [x for x in self.ant_iter(accept=accept, pats=[to_pat(incl), to_pat(excl)], maxdepth=25, dir=dir, src=src, remove=kw.get('remove', True))] if kw.get('flat', False): return ' '.join([x.path_from(self) for x in ret]) return ret def find_nodes(self, find_dirs=True, find_files=True, match_fun=lambda x: True): # FIXME not part of the stable API: find_node vs find_nodes? consistency with argument names on other functions? x = """ Recursively finds nodes:: def configure(cnf): cnf.find_nodes() :param find_dirs: whether to return directories :param find_files: whether to return files :param match_fun: matching function, taking a node as parameter :rtype generator :return: a generator that iterates over all the requested files """ files = self.listdir() for f in files: node = self.make_node([f]) if os.path.isdir(node.abspath()): if find_dirs and match_fun(node): yield node gen = node.find_nodes(find_dirs, find_files, match_fun) for g in gen: yield g else: if find_files and match_fun(node): yield node # -------------------------------------------------------------------------------- # the following methods require the source/build folders (bld.srcnode/bld.bldnode) # using a subclass is a possibility, but is that really necessary? # -------------------------------------------------------------------------------- def is_src(self): """ True if the node is below the source directory note: !is_src does not imply is_bld() :rtype: bool """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) while cur.parent: if id(cur) == y: return False if id(cur) == x: return True cur = cur.parent return False def is_bld(self): """ True if the node is below the build directory note: !is_bld does not imply is_src :rtype: bool """ cur = self y = id(self.ctx.bldnode) while cur.parent: if id(cur) == y: return True cur = cur.parent return False def get_src(self): """ Return the equivalent src node (or self if not possible) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) lst = [] while cur.parent: if id(cur) == y: lst.reverse() return self.ctx.srcnode.make_node(lst) if id(cur) == x: return self lst.append(cur.name) cur = cur.parent return self def get_bld(self): """ Return the equivalent bld node (or self if not possible) :rtype: :py:class:`waflib.Node.Node` """ cur = self x = id(self.ctx.srcnode) y = id(self.ctx.bldnode) lst = [] while cur.parent: if id(cur) == y: return self if id(cur) == x: lst.reverse() return self.ctx.bldnode.make_node(lst) lst.append(cur.name) cur = cur.parent # the file is external to the current project, make a fake root in the current build directory lst.reverse() if lst and Utils.is_win32 and len(lst[0]) == 2 and lst[0].endswith(':'): lst[0] = lst[0][0] return self.ctx.bldnode.make_node(['__root__'] + lst) def find_resource(self, lst): """ Try to find a declared build node or a source file :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.get_bld().search(lst) if not node: self = self.get_src() node = self.find_node(lst) try: pat = node.abspath() if os.path.isdir(pat): return None except: pass return node def find_or_declare(self, lst): """ if 'self' is in build directory, try to return an existing node if no node is found, go to the source directory try to find an existing node in the source directory if no node is found, create it in the build directory :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.get_bld().search(lst) if node: if not os.path.isfile(node.abspath()): node.sig = None try: node.parent.mkdir() except: pass return node self = self.get_src() node = self.find_node(lst) if node: if not os.path.isfile(node.abspath()): node.sig = None try: node.parent.mkdir() except: pass return node node = self.get_bld().make_node(lst) node.parent.mkdir() return node def find_dir(self, lst): """ Search for a folder in the filesystem :param lst: path :type lst: string or list of string """ if isinstance(lst, str): lst = [x for x in split_path(lst) if x and x != '.'] node = self.find_node(lst) try: if not os.path.isdir(node.abspath()): return None except (OSError, AttributeError): # the node might be None, and raise an AttributeError return None return node # helpers for building things def change_ext(self, ext, ext_in=None): """ :return: A build node of the same path, but with a different extension :rtype: :py:class:`waflib.Node.Node` """ name = self.name if ext_in is None: k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext else: name = name[:- len(ext_in)] + ext return self.parent.find_or_declare([name]) def nice_path(self, env=None): """ Return the path seen from the launch directory. It is often used for printing nodes in the console to open files easily. :param env: unused, left for compatibility with waf 1.5 """ return self.path_from(self.ctx.launch_node()) def bldpath(self): "Path seen from the build directory default/src/foo.cpp" return self.path_from(self.ctx.bldnode) def srcpath(self): "Path seen from the source directory ../src/foo.cpp" return self.path_from(self.ctx.srcnode) def relpath(self): "If a file in the build directory, bldpath, else srcpath" cur = self x = id(self.ctx.bldnode) while cur.parent: if id(cur) == x: return self.bldpath() cur = cur.parent return self.srcpath() def bld_dir(self): "Build path without the file name" return self.parent.bldpath() def bld_base(self): "Build path without the extension: src/dir/foo(.cpp)" s = os.path.splitext(self.name)[0] return self.bld_dir() + os.sep + s def get_bld_sig(self): """ Node signature, assuming the file is in the build directory """ try: ret = self.ctx.hash_cache[id(self)] except KeyError: pass except AttributeError: self.ctx.hash_cache = {} else: return ret if not self.is_bld() or self.ctx.bldnode is self.ctx.srcnode: self.sig = Utils.h_file(self.abspath()) self.ctx.hash_cache[id(self)] = ret = self.sig return ret pickle_lock = Utils.threading.Lock() """Lock mandatory for thread-safe node serialization""" class Nod3(Node): """Mandatory subclass for thread-safe node serialization""" pass # do not remove debian/waf-1.6/waflib/Scripting.py0000664000000000000000000003475212145744415014051 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "Module called for configuring, compiling and installing targets" import os, shutil, traceback, errno, sys, stat from waflib import Utils, Configure, Logs, Options, ConfigSet, Context, Errors, Build, Node build_dir_override = None no_climb_commands = ['configure'] default_cmd = "build" def waf_entry_point(current_directory, version, wafdir): """ This is the main entry point, all Waf execution starts here. :param current_directory: absolute path representing the current directory :type current_directory: string :param version: version number :type version: string :param wafdir: absolute path representing the directory of the waf library :type wafdir: string """ Logs.init_log() if Context.WAFVERSION != version: Logs.error('Waf script %r and library %r do not match (directory %r)' % (version, Context.WAFVERSION, wafdir)) sys.exit(1) if '--version' in sys.argv: Context.run_dir = current_directory ctx = Context.create_context('options') ctx.curdir = current_directory ctx.parse_args() sys.exit(0) Context.waf_dir = wafdir Context.launch_dir = current_directory # if 'configure' is in the commands, do not search any further no_climb = os.environ.get('NOCLIMB', None) if not no_climb: for k in no_climb_commands: if k in sys.argv: no_climb = True break # try to find a lock file (if the project was configured) # at the same time, store the first wscript file seen cur = current_directory while cur: lst = os.listdir(cur) if Options.lockfile in lst: env = ConfigSet.ConfigSet() try: env.load(os.path.join(cur, Options.lockfile)) ino = os.stat(cur)[stat.ST_INO] except Exception: pass else: # check if the folder was not moved for x in [env.run_dir, env.top_dir, env.out_dir]: if Utils.is_win32: if cur == x: load = True break else: # if the filesystem features symlinks, compare the inode numbers try: ino2 = os.stat(x)[stat.ST_INO] except: pass else: if ino == ino2: load = True break else: Logs.warn('invalid lock file in %s' % cur) load = False if load: Context.run_dir = env.run_dir Context.top_dir = env.top_dir Context.out_dir = env.out_dir break if not Context.run_dir: if Context.WSCRIPT_FILE in lst: Context.run_dir = cur next = os.path.dirname(cur) if next == cur: break cur = next if no_climb: break if not Context.run_dir: if '-h' in sys.argv or '--help' in sys.argv: Logs.warn('No wscript file found: the help message may be incomplete') Context.run_dir = current_directory ctx = Context.create_context('options') ctx.curdir = current_directory ctx.parse_args() sys.exit(0) Logs.error('Waf: Run from a directory containing a file named %r' % Context.WSCRIPT_FILE) sys.exit(1) try: os.chdir(Context.run_dir) except OSError: Logs.error('Waf: The folder %r is unreadable' % Context.run_dir) sys.exit(1) try: set_main_module(Context.run_dir + os.sep + Context.WSCRIPT_FILE) except Errors.WafError as e: Logs.pprint('RED', e.verbose_msg) Logs.error(str(e)) sys.exit(1) except Exception as e: Logs.error('Waf: The wscript in %r is unreadable' % Context.run_dir, e) traceback.print_exc(file=sys.stdout) sys.exit(2) """ import cProfile, pstats cProfile.runctx("import Scripting; Scripting.run_commands()", {}, {}, 'profi.txt') p = pstats.Stats('profi.txt') p.sort_stats('time').print_stats(25) """ try: run_commands() except Errors.WafError as e: if Logs.verbose > 1: Logs.pprint('RED', e.verbose_msg) Logs.error(e.msg) sys.exit(1) except Exception as e: traceback.print_exc(file=sys.stdout) sys.exit(2) except KeyboardInterrupt: Logs.pprint('RED', 'Interrupted') sys.exit(68) #""" def set_main_module(file_path): """ Read the main wscript file into :py:const:`waflib.Context.Context.g_module` and bind default functions such as ``init``, ``dist``, ``distclean`` if not defined. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. :param file_path: absolute path representing the top-level wscript file :type file_path: string """ Context.g_module = Context.load_module(file_path) Context.g_module.root_path = file_path # note: to register the module globally, use the following: # sys.modules['wscript_main'] = g_module def set_def(obj): name = obj.__name__ if not name in Context.g_module.__dict__: setattr(Context.g_module, name, obj) for k in [update, dist, distclean, distcheck, update]: set_def(k) # add dummy init and shutdown functions if they're not defined if not 'init' in Context.g_module.__dict__: Context.g_module.init = Utils.nada if not 'shutdown' in Context.g_module.__dict__: Context.g_module.shutdown = Utils.nada if not 'options' in Context.g_module.__dict__: Context.g_module.options = Utils.nada def parse_options(): """ Parse the command-line options and initialize the logging system. Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization. """ Context.create_context('options').execute() if not Options.commands: Options.commands = [default_cmd] Options.commands = [x for x in Options.commands if x != 'options'] # issue 1076 # process some internal Waf options Logs.verbose = Options.options.verbose Logs.init_log() if Options.options.zones: Logs.zones = Options.options.zones.split(',') if not Logs.verbose: Logs.verbose = 1 elif Logs.verbose > 0: Logs.zones = ['runner'] if Logs.verbose > 2: Logs.zones = ['*'] def run_command(cmd_name): """ Execute a single command. Called by :py:func:`waflib.Scripting.run_commands`. :param cmd_name: command to execute, like ``build`` :type cmd_name: string """ ctx = Context.create_context(cmd_name) ctx.options = Options.options # provided for convenience ctx.cmd = cmd_name ctx.execute() return ctx def run_commands(): """ Execute the commands that were given on the command-line, and the other options Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed after :py:func:`waflib.Scripting.parse_options`. """ parse_options() run_command('init') while Options.commands: cmd_name = Options.commands.pop(0) timer = Utils.Timer() run_command(cmd_name) if not Options.options.progress_bar: elapsed = ' (%s)' % str(timer) Logs.info('%r finished successfully%s' % (cmd_name, elapsed)) run_command('shutdown') ########################################################################################### def _can_distclean(name): # WARNING: this method may disappear anytime for k in '.o .moc .exe'.split(): if name.endswith(k): return True return False def distclean_dir(dirname): """ Distclean function called in the particular case when:: top == out :param dirname: absolute path of the folder to clean :type dirname: string """ for (root, dirs, files) in os.walk(dirname): for f in files: if _can_distclean(f): fname = root + os.sep + f try: os.unlink(fname) except: Logs.warn('could not remove %r' % fname) for x in [Context.DBFILE, 'config.log']: try: os.unlink(x) except: pass try: shutil.rmtree('c4che') except: pass def distclean(ctx): '''removes the build directory''' lst = os.listdir('.') for f in lst: if f == Options.lockfile: try: proj = ConfigSet.ConfigSet(f) except: Logs.warn('could not read %r' % f) continue if proj['out_dir'] != proj['top_dir']: try: shutil.rmtree(proj['out_dir']) except IOError: pass except OSError as e: if e.errno != errno.ENOENT: Logs.warn('project %r cannot be removed' % proj[Context.OUT]) else: distclean_dir(proj['out_dir']) for k in (proj['out_dir'], proj['top_dir'], proj['run_dir']): try: os.remove(os.path.join(k, Options.lockfile)) except OSError as e: if e.errno != errno.ENOENT: Logs.warn('file %r cannot be removed' % f) # remove the local waf cache if f.startswith('.waf') and not Options.commands: shutil.rmtree(f, ignore_errors=True) class Dist(Context.Context): """ Create an archive containing the project source code:: $ waf dist """ cmd = 'dist' fun = 'dist' algo = 'tar.bz2' ext_algo = {} def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() def archive(self): """ Create the archive. """ import tarfile arch_name = self.get_arch_name() try: self.base_path except: self.base_path = self.path node = self.base_path.make_node(arch_name) try: node.delete() except: pass files = self.get_files() if self.algo.startswith('tar.'): tar = tarfile.open(arch_name, 'w:' + self.algo.replace('tar.', '')) for x in files: self.add_tar_file(x, tar) tar.close() elif self.algo == 'zip': import zipfile zip = zipfile.ZipFile(arch_name, 'w', compression=zipfile.ZIP_DEFLATED) for x in files: archive_name = self.get_base_name() + '/' + x.path_from(self.base_path) zip.write(x.abspath(), archive_name, zipfile.ZIP_DEFLATED) zip.close() else: self.fatal('Valid algo types are tar.bz2, tar.gz or zip') try: from hashlib import sha1 as sha except ImportError: from sha import sha try: digest = " (sha=%r)" % sha(node.read()).hexdigest() except: digest = '' Logs.info('New archive created: %s%s' % (self.arch_name, digest)) def get_tar_path(self, node): """ return the path to use for a node in the tar archive, the purpose of this is to let subclases resolve symbolic links or to change file names """ return node.abspath() def add_tar_file(self, x, tar): """ Add a file to the tar archive. Transform symlinks into files if the files lie out of the project tree. """ p = self.get_tar_path(x) tinfo = tar.gettarinfo(name=p, arcname=self.get_tar_prefix() + '/' + x.path_from(self.base_path)) tinfo.uid = 0 tinfo.gid = 0 tinfo.uname = 'root' tinfo.gname = 'root' fu = None try: fu = open(p, 'rb') tar.addfile(tinfo, fileobj=fu) finally: if fu: fu.close() def get_tar_prefix(self): try: return self.tar_prefix except: return self.get_base_name() def get_arch_name(self): """ Return the name of the archive to create. Change the default value by setting *arch_name*:: def dist(ctx): ctx.arch_name = 'ctx.tar.bz2' :rtype: string """ try: self.arch_name except: self.arch_name = self.get_base_name() + '.' + self.ext_algo.get(self.algo, self.algo) return self.arch_name def get_base_name(self): """ Return the default name of the main directory in the archive, which is set to *appname-version*. Set the attribute *base_name* to change the default value:: def dist(ctx): ctx.base_name = 'files' :rtype: string """ try: self.base_name except: appname = getattr(Context.g_module, Context.APPNAME, 'noname') version = getattr(Context.g_module, Context.VERSION, '1.0') self.base_name = appname + '-' + version return self.base_name def get_excl(self): """ Return the patterns to exclude for finding the files in the top-level directory. Set the attribute *excl* to change the default value:: def dist(ctx): ctx.excl = 'build **/*.o **/*.class' :rtype: string """ try: return self.excl except: self.excl = Node.exclude_regs + ' **/waf-1.6.* **/.waf-1.6* **/waf3-1.6.* **/.waf3-1.6* **/*~ **/*.rej **/*.orig **/*.pyc **/*.pyo **/*.bak **/*.swp **/.lock-w*' nd = self.root.find_node(Context.out_dir) if nd: self.excl += ' ' + nd.path_from(self.base_path) return self.excl def get_files(self): """ The files to package are searched automatically by :py:func:`waflib.Node.Node.ant_glob`. Set *files* to prevent this behaviour:: def dist(ctx): ctx.files = ctx.path.find_node('wscript') The files are searched from the directory 'base_path', to change it, set:: def dist(ctx): ctx.base_path = path :rtype: list of :py:class:`waflib.Node.Node` """ try: files = self.files except: files = self.base_path.ant_glob('**/*', excl=self.get_excl()) return files def dist(ctx): '''makes a tarball for redistributing the sources''' pass class DistCheck(Dist): """ Create an archive of the project, and try to build the project in a temporary directory:: $ waf distcheck """ fun = 'distcheck' cmd = 'distcheck' def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.recurse([os.path.dirname(Context.g_module.root_path)]) self.archive() self.check() def check(self): """ Create the archive, uncompress it and try to build the project """ import tempfile, tarfile t = None try: t = tarfile.open(self.get_arch_name()) for x in t: t.extract(x) finally: if t: t.close() instdir = tempfile.mkdtemp('.inst', self.get_base_name()) ret = Utils.subprocess.Popen([sys.argv[0], 'configure', 'install', 'uninstall', '--destdir=' + instdir], cwd=self.get_base_name()).wait() if ret: raise Errors.WafError('distcheck failed with code %i' % ret) if os.path.exists(instdir): raise Errors.WafError('distcheck succeeded, but files were left in %s' % instdir) shutil.rmtree(self.get_base_name()) def distcheck(ctx): '''checks if the project compiles (tarball from 'dist')''' pass def update(ctx): '''updates the plugins from the *waflib/extras* directory''' lst = Options.options.files.split(',') if not lst: lst = [x for x in Utils.listdir(Context.waf_dir + '/waflib/extras') if x.endswith('.py')] for x in lst: tool = x.replace('.py', '') try: Configure.download_tool(tool, force=True, ctx=ctx) except Errors.WafError: Logs.error('Could not find the tool %s in the remote repository' % x) def autoconfigure(execute_method): """ Decorator used to set the commands that can be configured automatically """ def execute(self): if not Configure.autoconfig: return execute_method(self) env = ConfigSet.ConfigSet() do_config = False try: env.load(os.path.join(Context.top_dir, Options.lockfile)) except Exception: Logs.warn('Configuring the project') do_config = True else: if env.run_dir != Context.run_dir: do_config = True else: h = 0 for f in env['files']: h = hash((h, Utils.readf(f, 'rb'))) do_config = h != env.hash if do_config: Options.commands.insert(0, self.cmd) Options.commands.insert(0, 'configure') return return execute_method(self) return execute Build.BuildContext.execute = autoconfigure(Build.BuildContext.execute) debian/waf-1.6/waflib/TaskGen.py0000664000000000000000000005201512145744415013433 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Task generators The class :py:class:`waflib.TaskGen.task_gen` encapsulates the creation of task objects (low-level code) The instances can have various parameters, but the creation of task nodes (Task.py) is always postponed. To achieve this, various methods are called from the method "apply" """ import copy, re, os from waflib import Task, Utils, Logs, Errors, ConfigSet feats = Utils.defaultdict(set) """remember the methods declaring features""" class task_gen(object): """ Instances of this class create :py:class:`waflib.Task.TaskBase` when calling the method :py:meth:`waflib.TaskGen.task_gen.post` from the main thread. A few notes: * The methods to call (*self.meths*) can be specified dynamically (removing, adding, ..) * The 'features' are used to add methods to self.meths and then execute them * The attribute 'path' is a node representing the location of the task generator * The tasks created are added to the attribute *tasks* * The attribute 'idx' is a counter of task generators in the same path """ mappings = {} prec = Utils.defaultdict(list) def __init__(self, *k, **kw): """ The task generator objects predefine various attributes (source, target) for possible processing by process_rule (make-like rules) or process_source (extensions, misc methods) The tasks are stored on the attribute 'tasks'. They are created by calling methods listed in self.meths *or* referenced in the attribute features A topological sort is performed to ease the method re-use. The extra key/value elements passed in kw are set as attributes """ # so we will have to play with directed acyclic graphs # detect cycles, etc self.source = '' self.target = '' self.meths = [] """ List of method names to execute (it is usually a good idea to avoid touching this) """ self.prec = Utils.defaultdict(list) """ Precedence table for sorting the methods in self.meths """ self.mappings = {} """ List of mappings {extension -> function} for processing files by extension """ self.features = [] """ List of feature names for bringing new methods in """ self.tasks = [] """ List of tasks created. """ if not 'bld' in kw: # task generators without a build context :-/ self.env = ConfigSet.ConfigSet() self.idx = 0 self.path = None else: self.bld = kw['bld'] self.env = self.bld.env.derive() self.path = self.bld.path # emulate chdir when reading scripts # provide a unique id try: self.idx = self.bld.idx[id(self.path)] = self.bld.idx.get(id(self.path), 0) + 1 except AttributeError: self.bld.idx = {} self.idx = self.bld.idx[id(self.path)] = 1 for key, val in kw.items(): setattr(self, key, val) def __str__(self): """for debugging purposes""" return "" % (self.name, self.path.abspath()) def __repr__(self): """for debugging purposes""" lst = [] for x in self.__dict__.keys(): if x not in ['env', 'bld', 'compiled_tasks', 'tasks']: lst.append("%s=%s" % (x, repr(getattr(self, x)))) return "bld(%s) in %s" % (", ".join(lst), self.path.abspath()) def get_name(self): """ If not set, the name is computed from the target name:: def build(bld): x = bld(name='foo') x.get_name() # foo y = bld(target='bar') y.get_name() # bar :rtype: string :return: name of this task generator """ try: return self._name except AttributeError: if isinstance(self.target, list): lst = [str(x) for x in self.target] name = self._name = ','.join(lst) else: name = self._name = str(self.target) return name def set_name(self, name): self._name = name name = property(get_name, set_name) def to_list(self, val): """ Ensure that a parameter is a list :type val: string or list of string :param val: input to return as a list :rtype: list """ if isinstance(val, str): return val.split() else: return val def post(self): """ Create task objects. The following operations are performed: #. The body of this method is called only once and sets the attribute ``posted`` #. The attribute ``features`` is used to add more methods in ``self.meths`` #. The methods are sorted by the precedence table ``self.prec`` or `:waflib:attr:waflib.TaskGen.task_gen.prec` #. The methods are then executed in order #. The tasks created are added to :py:attr:`waflib.TaskGen.task_gen.tasks` """ # we could add a decorator to let the task run once, but then python 2.3 will be difficult to support if getattr(self, 'posted', None): #error("OBJECT ALREADY POSTED" + str( self)) return False self.posted = True keys = set(self.meths) # add the methods listed in the features self.features = Utils.to_list(self.features) for x in self.features + ['*']: st = feats[x] if not st: if not x in Task.classes: Logs.warn('feature %r does not exist - bind at least one method to it' % x) keys.update(list(st)) # ironpython 2.7 wants the cast to list # copy the precedence table prec = {} prec_tbl = self.prec or task_gen.prec for x in prec_tbl: if x in keys: prec[x] = prec_tbl[x] # elements disconnected tmp = [] for a in keys: for x in prec.values(): if a in x: break else: tmp.append(a) # TODO waf 1.7 #tmp.sort() # topological sort out = [] while tmp: e = tmp.pop() if e in keys: out.append(e) try: nlst = prec[e] except KeyError: pass else: del prec[e] for x in nlst: for y in prec: if x in prec[y]: break else: tmp.append(x) if prec: raise Errors.WafError('Cycle detected in the method execution %r' % prec) out.reverse() self.meths = out # then we run the methods in order Logs.debug('task_gen: posting %s %d' % (self, id(self))) for x in out: try: v = getattr(self, x) except AttributeError: raise Errors.WafError('%r is not a valid task generator method' % x) Logs.debug('task_gen: -> %s (%d)' % (x, id(self))) v() Logs.debug('task_gen: posted %s' % self.name) return True def get_hook(self, node): """ :param node: Input file to process :type node: :py:class:`waflib.Tools.Node.Node` :return: A method able to process the input node by looking at the extension :rtype: function """ name = node.name for k in self.mappings: if name.endswith(k): return self.mappings[k] for k in task_gen.mappings: if name.endswith(k): return task_gen.mappings[k] raise Errors.WafError("File %r has no mapping in %r (did you forget to load a waf tool?)" % (node, task_gen.mappings.keys())) def create_task(self, name, src=None, tgt=None): """ Wrapper for creating task objects easily :param name: task class name :type name: string :param src: input nodes :type src: list of :py:class:`waflib.Tools.Node.Node` :param tgt: output nodes :type tgt: list of :py:class:`waflib.Tools.Node.Node` :return: A task object :rtype: :py:class:`waflib.Task.TaskBase` """ task = Task.classes[name](env=self.env.derive(), generator=self) if src: task.set_inputs(src) if tgt: task.set_outputs(tgt) self.tasks.append(task) return task def clone(self, env): """ Make a copy of a task generator. Once the copy is made, it is necessary to ensure that the task generator does not create the same output files as the original, or the same files may be compiled twice. :param env: A configuration set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :return: A copy :rtype: :py:class:`waflib.TaskGen.task_gen` """ newobj = self.bld() for x in self.__dict__: if x in ['env', 'bld']: continue elif x in ['path', 'features']: setattr(newobj, x, getattr(self, x)) else: setattr(newobj, x, copy.copy(getattr(self, x))) newobj.posted = False if isinstance(env, str): newobj.env = self.bld.all_envs[env].derive() else: newobj.env = env.derive() return newobj def declare_chain(name='', rule=None, reentrant=None, color='BLUE', ext_in=[], ext_out=[], before=[], after=[], decider=None, scan=None, install_path=None, shell=False): """ Create a new mapping and a task class for processing files by extension. See Tools/flex.py for an example. :param name: name for the task class :type name: string :param rule: function to execute or string to be compiled in a function :type rule: string or function :param reentrant: re-inject the output file in the process (done automatically, set to 0 to disable) :type reentrant: int :param color: color for the task output :type color: string :param ext_in: execute the task only after the files of such extensions are created :type ext_in: list of string :param ext_out: execute the task only before files of such extensions are processed :type ext_out: list of string :param before: execute instances of this task before classes of the given names :type before: list of string :param after: execute instances of this task after classes of the given names :type after: list of string :param decider: if present, use it to create the output nodes for the task :type decider: function :param scan: scanner function for the task :type scan: function :param install_path: installation path for the output nodes :type install_path: string """ ext_in = Utils.to_list(ext_in) ext_out = Utils.to_list(ext_out) if not name: name = rule cls = Task.task_factory(name, rule, color=color, ext_in=ext_in, ext_out=ext_out, before=before, after=after, scan=scan, shell=shell) def x_file(self, node): ext = decider and decider(self, node) or cls.ext_out if ext_in: _ext_in = ext_in[0] tsk = self.create_task(name, node) cnt = 0 keys = self.mappings.keys() + self.__class__.mappings.keys() for x in ext: k = node.change_ext(x, ext_in=_ext_in) tsk.outputs.append(k) if reentrant != None: if cnt < int(reentrant): self.source.append(k) else: for y in keys: # ~ nfile * nextensions :-/ if k.name.endswith(y): self.source.append(k) break cnt += 1 if install_path: self.bld.install_files(install_path, tsk.outputs) return tsk for x in cls.ext_in: task_gen.mappings[x] = x_file return x_file def taskgen_method(func): """ Decorator: register a method as a task generator method. The function must accept a task generator as first parameter:: from waflib.TaskGen import taskgen_method @taskgen_method def mymethod(self): pass :param func: task generator method to add :type func: function :rtype: function """ setattr(task_gen, func.__name__, func) return func def feature(*k): """ Decorator: register a task generator method that will be executed when the object attribute 'feature' contains the corresponding key(s):: from waflib.Task import feature @feature('myfeature') def myfunction(self): print('that is my feature!') def build(bld): bld(features='myfeature') :param k: feature names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for name in k: feats[name].update([func.__name__]) return func return deco def before_method(*k): """ Decorator: register a task generator method which will be executed before the functions of given name(s):: from waflib.TaskGen import feature, before @feature('myfeature') @before_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not func.__name__ in task_gen.prec[fun_name]: task_gen.prec[fun_name].append(func.__name__) #task_gen.prec[fun_name].sort() return func return deco before = before_method def after_method(*k): """ Decorator: register a task generator method which will be executed after the functions of given name(s):: from waflib.TaskGen import feature, after @feature('myfeature') @after_method('fun2') def fun1(self): print('feature 1!') @feature('myfeature') def fun2(self): print('feature 2!') def build(bld): bld(features='myfeature') :param k: method names :type k: list of string """ def deco(func): setattr(task_gen, func.__name__, func) for fun_name in k: if not fun_name in task_gen.prec[func.__name__]: task_gen.prec[func.__name__].append(fun_name) #task_gen.prec[func.__name__].sort() return func return deco after = after_method def extension(*k): """ Decorator: register a task generator method which will be invoked during the processing of source files for the extension given:: from waflib import Task class mytask(Task): run_str = 'cp ${SRC} ${TGT}' @extension('.moo') def create_maa_file(self, node): self.create_task('mytask', node, node.change_ext('.maa')) def build(bld): bld(source='foo.moo') """ def deco(func): setattr(task_gen, func.__name__, func) for x in k: task_gen.mappings[x] = func return func return deco # --------------------------------------------------------------- # The following methods are task generator methods commonly used # they are almost examples, the rest of waf core does not depend on them @taskgen_method def to_nodes(self, lst, path=None): """ Convert the input list into a list of nodes. It is used by :py:func:`waflib.TaskGen.process_source` and :py:func:`waflib.TaskGen.process_rule`. It is designed for source files, for folders, see :py:func:`waflib.Tools.ccroot.to_incnodes`: :param lst: input list :type lst: list of string and nodes :param path: path from which to search the nodes (by default, :py:attr:`waflib.TaskGen.task_gen.path`) :type path: :py:class:`waflib.Tools.Node.Node` :rtype: list of :py:class:`waflib.Tools.Node.Node` """ tmp = [] path = path or self.path find = path.find_resource if isinstance(lst, self.path.__class__): lst = [lst] # either a list or a string, convert to a list of nodes for x in Utils.to_list(lst): if isinstance(x, str): node = find(x) else: node = x if not node: raise Errors.WafError("source not found: %r in %r" % (x, self)) tmp.append(node) return tmp @feature('*') def process_source(self): """ Process each element in the attribute ``source`` by extension. #. The *source* list is converted through :py:meth:`waflib.TaskGen.to_nodes` to a list of :py:class:`waflib.Node.Node` first. #. File extensions are mapped to methods having the signature: ``def meth(self, node)`` by :py:meth:`waflib.TaskGen.extension` #. The method is retrieved through :py:meth:`waflib.TaskGen.task_gen.get_hook` #. When called, the methods may modify self.source to append more source to process #. The mappings can map an extension or a filename (see the code below) """ self.source = self.to_nodes(getattr(self, 'source', [])) for node in self.source: self.get_hook(node)(self, node) @feature('*') @before_method('process_source') def process_rule(self): """ Process the attribute ``rule``. When present, :py:meth:`waflib.TaskGen.process_source` is disabled:: def build(bld): bld(rule='cp ${SRC} ${TGT}', source='wscript', target='bar.txt') """ if not getattr(self, 'rule', None): return # create the task class name = str(getattr(self, 'name', None) or self.target or self.rule) cls = Task.task_factory(name, self.rule, getattr(self, 'vars', []), shell=getattr(self, 'shell', True), color=getattr(self, 'color', 'BLUE')) # now create one instance tsk = self.create_task(name) if getattr(self, 'target', None): if isinstance(self.target, str): self.target = self.target.split() if not isinstance(self.target, list): self.target = [self.target] for x in self.target: if isinstance(x, str): tsk.outputs.append(self.path.find_or_declare(x)) else: x.parent.mkdir() # if a node was given, create the required folders tsk.outputs.append(x) if getattr(self, 'install_path', None): # from waf 1.5 # although convenient, it does not 1. allow to name the target file and 2. symlinks # TODO remove in waf 1.7 self.bld.install_files(self.install_path, tsk.outputs) if getattr(self, 'source', None): tsk.inputs = self.to_nodes(self.source) # bypass the execution of process_source by setting the source to an empty list self.source = [] if getattr(self, 'scan', None): cls.scan = self.scan elif getattr(self, 'deps', None): def scan(self): nodes = [] for x in self.generator.to_list(self.generator.deps): node = self.generator.path.find_resource(x) if not node: self.generator.bld.fatal('Could not find %r (was it declared?)' % x) nodes.append(node) return [nodes, []] cls.scan = scan if getattr(self, 'cwd', None): tsk.cwd = self.cwd # TODO remove on_results in waf 1.7 if getattr(self, 'update_outputs', None) or getattr(self, 'on_results', None): Task.update_outputs(cls) if getattr(self, 'always', None): Task.always_run(cls) for x in ['after', 'before', 'ext_in', 'ext_out']: setattr(cls, x, getattr(self, x, [])) @feature('seq') def sequence_order(self): """ Add a strict sequential constraint between the tasks generated by task generators. It works because task generators are posted in order. It will not post objects which belong to other folders. Example:: bld(features='javac seq') bld(features='jar seq') To start a new sequence, set the attribute seq_start, for example:: obj = bld(features='seq') obj.seq_start = True Note that the method is executed in last position. This is more an example than a widely-used solution. """ if self.meths and self.meths[-1] != 'sequence_order': self.meths.append('sequence_order') return if getattr(self, 'seq_start', None): return # all the tasks previously declared must be run before these if getattr(self.bld, 'prev', None): self.bld.prev.post() for x in self.bld.prev.tasks: for y in self.tasks: y.set_run_after(x) self.bld.prev = self re_m4 = re.compile('@(\w+)@', re.M) class subst_pc(Task.Task): """ Create *.pc* files from *.pc.in*. The task is executed whenever an input variable used in the substitution changes. """ def run(self): "Substitutes variables in a .in file" code = self.inputs[0].read() # replace all % by %% to prevent errors by % signs code = code.replace('%', '%%') # extract the vars foo into lst and replace @foo@ by %(foo)s lst = [] def repl(match): g = match.group if g(1): lst.append(g(1)) return "%%(%s)s" % g(1) return '' code = re_m4.sub(repl, code) try: d = self.generator.dct except AttributeError: d = {} for x in lst: tmp = getattr(self.generator, x, '') or self.env.get_flat(x) or self.env.get_flat(x.upper()) d[x] = str(tmp) self.outputs[0].write(code % d) self.generator.bld.raw_deps[self.uid()] = self.dep_vars = lst # make sure the signature is updated try: delattr(self, 'cache_sig') except AttributeError: pass if getattr(self.generator, 'chmod', None): os.chmod(self.outputs[0].abspath(), self.generator.chmod) def sig_vars(self): """ Compute a hash (signature) of the variables used in the substitution """ bld = self.generator.bld env = self.env upd = self.m.update # raw_deps: persistent custom values returned by the scanner vars = self.generator.bld.raw_deps.get(self.uid(), []) # hash both env vars and task generator attributes act_sig = bld.hash_env_vars(env, vars) upd(act_sig) lst = [getattr(self.generator, x, '') for x in vars] upd(Utils.h_list(lst)) return self.m.digest() @extension('.pc.in') def add_pcfile(self, node): """ Process *.pc.in* files to *.pc*. Install the results to ``${PREFIX}/lib/pkgconfig/`` def build(bld): bld(source='foo.pc.in', install_path='${LIBDIR}/pkgconfig/') """ tsk = self.create_task('subst_pc', node, node.change_ext('.pc', '.pc.in')) self.bld.install_files(getattr(self, 'install_path', '${LIBDIR}/pkgconfig/'), tsk.outputs) class subst(subst_pc): pass @feature('subst') @before_method('process_source', 'process_rule') def process_subst(self): """ Define a transformation that substitutes the contents of *source* files to *target* files:: def build(bld): bld( features='subst', source='foo.c.in', target='foo.c', install_path='${LIBDIR}/pkgconfig', VAR = 'val' ) The input files are supposed to contain macros of the form *@VAR@*, where *VAR* is an argument of the task generator object. This method overrides the processing by :py:meth:`waflib.TaskGen.process_source`. """ src = self.to_nodes(getattr(self, 'source', [])) tgt = getattr(self, 'target', []) if isinstance(tgt, self.path.__class__): tgt = [tgt] tgt = [isinstance(x, self.path.__class__) and x or self.path.find_or_declare(x) for x in Utils.to_list(tgt)] if len(src) != len(tgt): raise Errors.WafError('invalid source or target for %r' % self) for x, y in zip(src, tgt): if not (x and y): raise Errors.WafError('invalid source or target for %r' % self) tsk = self.create_task('subst', x, y) for a in ('after', 'before', 'ext_in', 'ext_out'): val = getattr(self, a, None) if val: setattr(tsk, a, val) inst_to = getattr(self, 'install_path', None) if inst_to: self.bld.install_files(inst_to, tgt, chmod=getattr(self, 'chmod', Utils.O644)) self.source = [] debian/waf-1.6/waflib/Configure.py0000664000000000000000000003721512145744415014025 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Configuration system A :py:class:`waflib.Configure.ConfigurationContext` instance is created when ``waf configure`` is called, it is used to: * create data dictionaries (ConfigSet instances) * store the list of modules to import * hold configuration routines such as ``find_program``, etc """ import os, shlex, sys, time from waflib import ConfigSet, Utils, Options, Logs, Context, Build, Errors try: from urllib import request except: from urllib import urlopen else: urlopen = request.urlopen BREAK = 'break' """In case of a configuration error, break""" CONTINUE = 'continue' """In case of a configuration error, continue""" WAF_CONFIG_LOG = 'config.log' """Name of the configuration log file""" autoconfig = False """Execute the configuration automatically""" conf_template = '''# project %(app)s configured on %(now)s by # waf %(wafver)s (abi %(abi)s, python %(pyver)x on %(systype)s) # using %(args)s #''' def download_check(node): """ Hook to check for the tools which are downloaded. Replace with your function if necessary. """ pass def download_tool(tool, force=False, ctx=None): """ Download a Waf tool from the remote repository defined in :py:const:`waflib.Context.remote_repo`:: $ waf configure --download """ for x in Utils.to_list(Context.remote_repo): for sub in Utils.to_list(Context.remote_locs): url = '/'.join((x, sub, tool + '.py')) try: web = urlopen(url) try: if web.getcode() != 200: continue except AttributeError: pass except Exception: # on python3 urlopen throws an exception # python 2.3 does not have getcode and throws an exception to fail continue else: tmp = ctx.root.make_node(os.sep.join((Context.waf_dir, 'waflib', 'extras', tool + '.py'))) tmp.write(web.read()) Logs.warn('Downloaded %s from %s' % (tool, url)) download_check(tmp) try: module = Context.load_tool(tool) except: Logs.warn('The tool %s from %s is unusable' % (tool, url)) try: tmp.delete() except: pass continue return module raise Errors.WafError('Could not load the Waf tool') class ConfigurationContext(Context.Context): '''configures the project''' cmd = 'configure' error_handlers = [] """ Additional functions to handle configuration errors """ def __init__(self, **kw): super(ConfigurationContext, self).__init__(**kw) self.environ = dict(os.environ) self.all_envs = {} self.top_dir = None self.out_dir = None self.tools = [] # tools loaded in the configuration, and that will be loaded when building self.hash = 0 self.files = [] self.tool_cache = [] self.setenv('') def setenv(self, name, env=None): """ Set a new config set for conf.env. If a config set of that name already exists, recall it without modification. The name is the filename prefix to save to ``c4che/NAME_cache.py``, and it is also used as *variants* by the build commands. Though related to variants, whatever kind of data may be stored in the config set:: def configure(cfg): cfg.env.ONE = 1 cfg.setenv('foo') cfg.env.ONE = 2 def build(bld): 2 == bld.env_of_name('foo').ONE :param name: name of the configuration set :type name: string :param env: ConfigSet to copy, or an empty ConfigSet is created :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ if name not in self.all_envs or env: if not env: env = ConfigSet.ConfigSet() self.prepare_env(env) else: env = env.derive() self.all_envs[name] = env self.variant = name def get_env(self): """Getter for the env property""" return self.all_envs[self.variant] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def init_dirs(self): """ Initialize the project directory and the build directory """ top = self.top_dir if not top: top = Options.options.top if not top: top = getattr(Context.g_module, Context.TOP, None) if not top: top = self.path.abspath() top = os.path.abspath(top) self.srcnode = (os.path.isabs(top) and self.root or self.path).find_dir(top) assert(self.srcnode) out = self.out_dir if not out: out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf_%s_' % sys.platform, '').replace('.lock-waf', '') self.bldnode = (os.path.isabs(out) and self.root or self.path).make_node(out) self.bldnode.mkdir() if not os.path.isdir(self.bldnode.abspath()): conf.fatal('could not create the build directory %s' % self.bldnode.abspath()) def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.init_dirs() self.cachedir = self.bldnode.make_node(Build.CACHE_DIR) self.cachedir.mkdir() path = os.path.join(self.bldnode.abspath(), WAF_CONFIG_LOG) self.logger = Logs.make_logger(path, 'cfg') app = getattr(Context.g_module, 'APPNAME', '') if app: ver = getattr(Context.g_module, 'VERSION', '') if ver: app = "%s (%s)" % (app, ver) now = time.ctime() pyver = sys.hexversion systype = sys.platform args = " ".join(sys.argv) wafver = Context.WAFVERSION abi = Context.ABI self.to_log(conf_template % vars()) self.msg('Setting top to', self.srcnode.abspath()) self.msg('Setting out to', self.bldnode.abspath()) if id(self.srcnode) == id(self.bldnode): Logs.warn('Setting top == out (remember to use "update_outputs")') elif id(self.path) != id(self.srcnode): if self.srcnode.is_child_of(self.path): Logs.warn('Are you certain that you do not want to set top="." ?') super(ConfigurationContext, self).execute() self.store() Context.top_dir = self.srcnode.abspath() Context.out_dir = self.bldnode.abspath() # this will write a configure lock so that subsequent builds will # consider the current path as the root directory (see prepare_impl). # to remove: use 'waf distclean' env = ConfigSet.ConfigSet() env['argv'] = sys.argv env['options'] = Options.options.__dict__ env.run_dir = Context.run_dir env.top_dir = Context.top_dir env.out_dir = Context.out_dir # conf.hash & conf.files hold wscript files paths and hash # (used only by Configure.autoconfig) env['hash'] = self.hash env['files'] = self.files env['environ'] = dict(self.environ) if not self.env.NO_LOCK_IN_RUN: env.store(Context.run_dir + os.sep + Options.lockfile) if not self.env.NO_LOCK_IN_TOP: env.store(Context.top_dir + os.sep + Options.lockfile) if not self.env.NO_LOCK_IN_OUT: env.store(Context.out_dir + os.sep + Options.lockfile) def prepare_env(self, env): """ Insert *PREFIX*, *BINDIR* and *LIBDIR* values into ``env`` :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param env: a ConfigSet, usually ``conf.env`` """ if not env.PREFIX: env.PREFIX = os.path.abspath(os.path.expanduser(Options.options.prefix)) if not env.BINDIR: env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env) if not env.LIBDIR: env.LIBDIR = Utils.subst_vars('${PREFIX}/lib', env) def store(self): """Save the config results into the cache file""" n = self.cachedir.make_node('build.config.py') n.write('version = 0x%x\ntools = %r\n' % (Context.HEXVERSION, self.tools)) if not self.all_envs: self.fatal('nothing to store in the configuration context!') for key in self.all_envs: tmpenv = self.all_envs[key] tmpenv.store(os.path.join(self.cachedir.abspath(), key + Build.CACHE_SUFFIX)) def load(self, input, tooldir=None, funs=None, download=True): """ Load Waf tools, which will be imported whenever a build is started. :param input: waf tools to import :type input: list of string :param tooldir: paths for the imports :type tooldir: list of string :param funs: functions to execute from the waf tools :type funs: list of string :param download: whether to download the tool from the waf repository :type download: bool """ tools = Utils.to_list(input) if tooldir: tooldir = Utils.to_list(tooldir) for tool in tools: # avoid loading the same tool more than once with the same functions # used by composite projects mag = (tool, id(self.env), funs) if mag in self.tool_cache: self.to_log('(tool %s is already loaded, skipping)' % tool) continue self.tool_cache.append(mag) module = None try: module = Context.load_tool(tool, tooldir) except ImportError as e: if Options.options.download: module = download_tool(tool, ctx=self) if not module: self.fatal('Could not load the Waf tool %r or download a suitable replacement from the repository (sys.path %r)\n%s' % (tool, sys.path, e)) else: self.fatal('Could not load the Waf tool %r from %r (try the --download option?):\n%s' % (tool, sys.path, e)) except Exception as e: self.to_log('imp %r (%r & %r)' % (tool, tooldir, funs)) self.to_log(Utils.ex_stack()) raise if funs is not None: self.eval_rules(funs) else: func = getattr(module, 'configure', None) if func: if type(func) is type(Utils.readf): func(self) else: self.eval_rules(func) self.tools.append({'tool':tool, 'tooldir':tooldir, 'funs':funs}) def post_recurse(self, node): """ Records the path and a hash of the scripts visited, see :py:meth:`waflib.Context.Context.post_recurse` :param node: script :type node: :py:class:`waflib.Node.Node` """ super(ConfigurationContext, self).post_recurse(node) self.hash = hash((self.hash, node.read('rb'))) self.files.append(node.abspath()) def eval_rules(self, rules): """ Execute the configuration tests. The method :py:meth:`waflib.Configure.ConfigurationContext.err_handler` is used to process the eventual exceptions :param rules: list of configuration method names :type rules: list of string """ self.rules = Utils.to_list(rules) for x in self.rules: f = getattr(self, x) if not f: self.fatal("No such method '%s'." % x) try: f() except Exception as e: ret = self.err_handler(x, e) if ret == BREAK: break elif ret == CONTINUE: continue else: raise def err_handler(self, fun, error): """ Error handler for the configuration tests, the default is to let the exception raise :param fun: configuration test :type fun: method :param error: exception :type error: exception """ pass def conf(f): """ Decorator: attach new configuration functions to :py:class:`waflib.Build.BuildContext` and :py:class:`waflib.Configure.ConfigurationContext`. The methods bound will accept a parameter named 'mandatory' to disable the configuration errors:: def configure(conf): conf.find_program('abc', mandatory=False) :param f: method to bind :type f: function """ def fun(*k, **kw): mandatory = True if 'mandatory' in kw: mandatory = kw['mandatory'] del kw['mandatory'] try: return f(*k, **kw) except Errors.ConfigurationError as e: if mandatory: raise e setattr(ConfigurationContext, f.__name__, fun) setattr(Build.BuildContext, f.__name__, fun) return f @conf def add_os_flags(self, var, dest=None): """ Import operating system environment values into ``conf.env`` dict:: def configure(conf): conf.add_os_flags('CFLAGS') :param var: variable to use :type var: string :param dest: destination variable, by default the same as var :type dest: string """ # do not use 'get' to make certain the variable is not defined try: self.env.append_value(dest or var, shlex.split(self.environ[var])) except KeyError: pass @conf def cmd_to_list(self, cmd): """ Detect if a command is written in pseudo shell like ``ccache g++`` and return a list. :param cmd: command :type cmd: a string or a list of string """ if isinstance(cmd, str) and cmd.find(' '): try: os.stat(cmd) except OSError: return shlex.split(cmd) else: return [cmd] return cmd @conf def check_waf_version(self, mini='1.6.0', maxi='1.7.0'): """ check for the waf version Versions should be supplied as hex. 0x01000000 means 1.0.0, 0x010408 means 1.4.8, etc. :type mini: number, tuple or string :param mini: Minimum required version :type maxi: number, tuple or string :param maxi: Maximum allowed version """ self.start_msg('Checking for waf version in %s-%s' % (str(mini), str(maxi))) ver = Context.HEXVERSION if Utils.num2ver(mini) > ver: self.fatal('waf version should be at least %r (%r found)' % (Utils.num2ver(mini), ver)) if Utils.num2ver(maxi) < ver: self.fatal('waf version should be at most %r (%r found)' % (Utils.num2ver(maxi), ver)) self.end_msg('ok') @conf def find_file(self, filename, path_list=[]): """ Find a file in a list of paths :param filename: name of the file to search for :param path_list: list of directories to search :return: the first occurrence filename or '' if filename could not be found """ for n in Utils.to_list(filename): for d in Utils.to_list(path_list): p = os.path.join(d, n) if os.path.exists(p): return p self.fatal('Could not find %r' % filename) @conf def find_program(self, filename, **kw): """ Search for a program on the operating system When var is used, you may set os.environ[var] to help find a specific program version, for example:: $ VALAC=/usr/bin/valac_test waf configure :param path_list: paths to use for searching :type param_list: list of string :param var: store the result to conf.env[var], by default use filename.upper() :type var: string :param ext: list of extensions for the binary (do not add an extension for portability) :type ext: list of string """ exts = kw.get('exts', Utils.is_win32 and '.exe,.com,.bat,.cmd' or ',.sh,.pl,.py') environ = kw.get('environ', os.environ) ret = '' filename = Utils.to_list(filename) var = kw.get('var', '') if not var: var = filename[0].upper() if self.env[var]: ret = self.env[var] elif var in environ: ret = environ[var] path_list = kw.get('path_list', '') if not ret: if path_list: path_list = Utils.to_list(path_list) else: path_list = environ.get('PATH', '').split(os.pathsep) if not isinstance(filename, list): filename = [filename] for a in exts.split(','): if ret: break for b in filename: if ret: break for c in path_list: if ret: break x = os.path.expanduser(os.path.join(c, b + a)) if os.path.isfile(x): ret = x if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_CURRENT_USER, filename) if not ret and Utils.winreg: ret = Utils.get_registry_app_path(Utils.winreg.HKEY_LOCAL_MACHINE, filename) self.msg('Checking for program ' + ','.join(filename), ret or False) self.to_log('find program=%r paths=%r var=%r -> %r' % (filename, path_list, var, ret)) if not ret: self.fatal(kw.get('errmsg', '') or 'Could not find the program %s' % ','.join(filename)) if var: self.env[var] = ret return ret @conf def find_perl_program(self, filename, path_list=[], var=None, environ=None, exts=''): """ Search for a perl program on the operating system :param filename: file to search for :type filename: string :param path_list: list of paths to look into :type path_list: list of string :param var: store the results into *conf.env.var* :type var: string :param environ: operating system environment to pass to :py:func:`waflib.Configure.find_program` :type environ: dict :param exts: extensions given to :py:func:`waflib.Configure.find_program` :type exts: list """ try: app = self.find_program(filename, path_list=path_list, var=var, environ=environ, exts=exts) except: self.find_program('perl', var='PERL') app = self.find_file(filename, os.environ['PATH'].split(os.pathsep)) if not app: raise if var: self.env[var] = Utils.to_list(self.env['PERL']) + [app] self.msg('Checking for %r' % filename, app) debian/waf-1.6/waflib/Runner.py0000664000000000000000000002065512145744415013355 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Runner.py: Task scheduling and execution """ import random, atexit try: from queue import Queue except: from Queue import Queue from waflib import Utils, Task, Errors, Logs GAP = 10 """ Wait for free tasks if there are at least ``GAP * njobs`` in queue """ class TaskConsumer(Utils.threading.Thread): """ Task consumers belong to a pool of workers They wait for tasks in the queue and then use ``task.process(...)`` """ def __init__(self): Utils.threading.Thread.__init__(self) self.ready = Queue() """ Obtain :py:class:`waflib.Task.TaskBase` instances from this queue. """ self.setDaemon(1) self.start() def run(self): """ Loop over the tasks to execute """ try: self.loop() except: pass def loop(self): """ Obtain tasks from :py:attr:`waflib.Runner.TaskConsumer.ready` and call :py:meth:`waflib.Task.TaskBase.process`. If the object is a function, execute it. """ while 1: tsk = self.ready.get() if not isinstance(tsk, Task.TaskBase): tsk(self) else: tsk.process() pool = Queue() """ Pool of task consumer objects """ def get_pool(): """ Obtain a task consumer from :py:attr:`waflib.Runner.pool`. Do not forget to put it back by using :py:func:`waflib.Runner.put_pool` and reset properly (original waiting queue). :rtype: :py:class:`waflib.Runner.TaskConsumer` """ try: return pool.get(False) except: return TaskConsumer() def put_pool(x): """ Return a task consumer to the thread pool :py:attr:`waflib.Runner.pool` :param x: task consumer object :type x: :py:class:`waflib.Runner.TaskConsumer` """ pool.put(x) def _free_resources(): global pool lst = [] while pool.qsize(): lst.append(pool.get()) for x in lst: x.ready.put(None) for x in lst: x.join() pool = None atexit.register(_free_resources) class Parallel(object): """ Schedule the tasks obtained from the build context for execution. """ def __init__(self, bld, j=2): """ The initialization requires a build context reference for computing the total number of jobs. """ self.numjobs = j """ Number of consumers in the pool """ self.bld = bld """ Instance of :py:class:`waflib.Build.BuildContext` """ self.outstanding = [] """List of :py:class:`waflib.Task.TaskBase` that may be ready to be executed""" self.frozen = [] """List of :py:class:`waflib.Task.TaskBase` that cannot be executed immediately""" self.out = Queue(0) """List of :py:class:`waflib.Task.TaskBase` returned by the task consumers""" self.count = 0 """Amount of tasks that may be processed by :py:class:`waflib.Runner.TaskConsumer`""" self.processed = 1 """Amount of tasks processed""" self.stop = False """Error flag to stop the build""" self.error = [] """Tasks that could not be executed""" self.biter = None """Task iterator which must give groups of parallelizable tasks when calling ``next()``""" self.dirty = False """Flag to indicate that tasks have been executed, and that the build cache must be saved (call :py:meth:`waflib.Build.BuildContext.store`)""" def get_next_task(self): """ Obtain the next task to execute. :rtype: :py:class:`waflib.Task.TaskBase` """ if not self.outstanding: return None return self.outstanding.pop(0) def postpone(self, tsk): """ A task cannot be executed at this point, put it in the list :py:attr:`waflib.Runner.Parallel.frozen`. :param tsk: task :type tsk: :py:class:`waflib.Task.TaskBase` """ if random.randint(0, 1): self.frozen.insert(0, tsk) else: self.frozen.append(tsk) def refill_task_list(self): """ Put the next group of tasks to execute in :py:attr:`waflib.Runner.Parallel.outstanding`. """ while self.count > self.numjobs * GAP: self.get_out() while not self.outstanding: if self.count: self.get_out() elif self.frozen: try: cond = self.deadlock == self.processed except: pass else: if cond: msg = 'check the build order for the tasks' for tsk in self.frozen: if not tsk.run_after: msg = 'check the methods runnable_status' break lst = [] for tsk in self.frozen: lst.append('%s\t-> %r' % (repr(tsk), [id(x) for x in tsk.run_after])) raise Errors.WafError('Deadlock detected: %s%s' % (msg, ''.join(lst))) self.deadlock = self.processed if self.frozen: self.outstanding += self.frozen self.frozen = [] elif not self.count: self.outstanding.extend(next(self.biter)) self.total = self.bld.total() break def add_more_tasks(self, tsk): """ Tasks may be added dynamically during the build by binding them to the task :py:attr:`waflib.Task.TaskBase.more_tasks` :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ if getattr(tsk, 'more_tasks', None): self.outstanding += tsk.more_tasks self.total += len(tsk.more_tasks) def get_out(self): """ Obtain one task returned from the task consumers, and update the task count. Add more tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`. :rtype: :py:attr:`waflib.Task.TaskBase` """ tsk = self.out.get() if not self.stop: self.add_more_tasks(tsk) self.count -= 1 self.dirty = True return tsk def error_handler(self, tsk): """ Called when a task cannot be executed. The flag :py:attr:`waflib.Runner.Parallel.stop` is set, unless the build is executed with:: $ waf build -k :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ if not self.bld.keep: self.stop = True self.error.append(tsk) def add_task(self, tsk): """ Pass a task to a consumer. :param tsk: task :type tsk: :py:attr:`waflib.Task.TaskBase` """ try: self.pool except AttributeError: self.init_task_pool() self.ready.put(tsk) def init_task_pool(self): # lazy creation, and set a common pool for all task consumers pool = self.pool = [get_pool() for i in range(self.numjobs)] self.ready = Queue(0) def setq(consumer): consumer.ready = self.ready for x in pool: x.ready.put(setq) return pool def free_task_pool(self): # return the consumers, setting a different queue for each of them def setq(consumer): consumer.ready = Queue(0) self.out.put(self) try: pool = self.pool except: pass else: for x in pool: self.ready.put(setq) for x in pool: self.get_out() for x in pool: put_pool(x) self.pool = [] def start(self): """ Give tasks to :py:class:`waflib.Runner.TaskConsumer` instances until the build finishes or the ``stop`` flag is set. If only one job is used, then execute the tasks one by one, without consumers. """ self.total = self.bld.total() while not self.stop: self.refill_task_list() # consider the next task tsk = self.get_next_task() if not tsk: if self.count: # tasks may add new ones after they are run continue else: # no tasks to run, no tasks running, time to exit break if tsk.hasrun: # if the task is marked as "run", just skip it self.processed += 1 continue if self.stop: # stop immediately after a failure was detected break try: st = tsk.runnable_status() except Exception: self.processed += 1 # TODO waf 1.7 this piece of code should go in the error_handler tsk.err_msg = Utils.ex_stack() if not self.stop and self.bld.keep: tsk.hasrun = Task.SKIPPED if self.bld.keep == 1: # if -k stop at the first exception, if -kk try to go as far as possible if Logs.verbose > 1 or not self.error: self.error.append(tsk) self.stop = True else: if Logs.verbose > 1: self.error.append(tsk) continue tsk.hasrun = Task.EXCEPTION self.error_handler(tsk) continue if st == Task.ASK_LATER: self.postpone(tsk) elif st == Task.SKIP_ME: self.processed += 1 tsk.hasrun = Task.SKIPPED self.add_more_tasks(tsk) else: # run me: put the task in ready queue tsk.position = (self.processed, self.total) self.count += 1 tsk.master = self self.processed += 1 if self.numjobs == 1: tsk.process() else: self.add_task(tsk) # self.count represents the tasks that have been made available to the consumer threads # collect all the tasks after an error else the message may be incomplete while self.error and self.count: self.get_out() #print loop assert (self.count == 0 or self.stop) # free the task pool, if any self.free_task_pool() debian/waf-1.6/waflib/Tools/0000775000000000000000000000000012253225220012606 5ustar debian/waf-1.6/waflib/Tools/suncxx.py0000664000000000000000000000346012145744415014527 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_sxx(conf): """ Detect the sun C++ compiler """ v = conf.env cc = None if v['CXX']: cc = v['CXX'] elif 'CXX' in conf.environ: cc = conf.environ['CXX'] if not cc: cc = conf.find_program('CC', var='CXX') #studio if not cc: cc = conf.find_program('c++', var='CXX') if not cc: conf.fatal('Could not find a Sun C++ compiler') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-flags']) except: conf.fatal('%r is not a Sun compiler' % cc) v['CXX'] = cc v['CXX_NAME'] = 'sun' @conf def sxx_common_flags(conf): """ Flags required for executing the sun C++ compiler """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STLIB_MARKER'] = '-Bstatic' # program v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-Kpic', '-DPIC'] v['LINKFLAGS_cxxshlib'] = ['-G'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = ['-Bstatic'] v['cxxstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_sxx() conf.find_ar() conf.sxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/qt4.py0000664000000000000000000004606012145744415013712 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for the Qt4 libraries and tools:: def options(opt): opt.load('compiler_cxx qt4') def configure(conf): conf.load('compiler_cxx qt4') conf.env.append_value('CXXFLAGS', ['-g']) # test def build(bld): bld( features = 'qt4 cxx cxxprogram', uselib = 'QTCORE QTGUI QTOPENGL QTSVG', source = 'main.cpp textures.qrc aboutDialog.ui', target = 'window', ) The C++ files must include the .moc files, which is regarded as the best practice (much faster compilations). This also implies that the include paths have to be set properly. To have the include paths added automatically, use the following:: from waflib.TaskGen import feature, before_method, after_method @feature('cxx') @after_method('process_source') @before_method('apply_incpaths') def add_includes_paths(self): incs = set(self.to_list(getattr(self, 'includes', ''))) for x in self.compiled_tasks: incs.add(x.inputs[0].parent.path_from(self.path)) self.includes = list(incs) Another tool provides a Qt processing that does not require the moc includes. See http://code.google.com/p/waf/source/browse/trunk/playground/slow_qt/ """ try: from xml.sax import make_parser from xml.sax.handler import ContentHandler except ImportError: has_xml = False ContentHandler = object else: has_xml = True import os, sys from waflib.Tools import c_preproc, cxx from waflib import Task, Utils, Options, Errors from waflib.TaskGen import feature, after_method, extension from waflib.Configure import conf from waflib import Logs MOC_H = ['.h', '.hpp', '.hxx', '.hh'] """ File extensions associated to the .moc files """ EXT_RCC = ['.qrc'] """ File extension for the resource (.qrc) files """ EXT_UI = ['.ui'] """ File extension for the user interface (.ui) files """ EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] """ File extensions of C++ files that may require a .moc processing """ QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative" class qxx(cxx.cxx): """ Each C++ file can have zero or several .moc files to create. They are known only when the files are scanned (preprocessor) To avoid scanning the c++ files each time (parsing C/C++), the results are retrieved from the task cache (bld.node_deps/bld.raw_deps). The moc tasks are also created *dynamically* during the build. """ def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.moc_done = 0 def scan(self): """Re-use the C/C++ scanner, but remove the moc files from the dependencies""" (nodes, names) = c_preproc.scan(self) # for some reasons (variants) the moc node may end in the list of node deps for x in nodes: if x.name.endswith('.moc'): nodes.remove(x) names.append(x.path_from(self.inputs[0].parent.get_bld())) return (nodes, names) def runnable_status(self): """ Compute the task signature to make sure the scanner was executed. Create the moc tasks by using :py:meth:`waflib.Tools.qt4.qxx.add_moc_tasks` (if necessary), then postpone the task execution (there is no need to recompute the task signature). """ if self.moc_done: return Task.Task.runnable_status(self) else: for t in self.run_after: if not t.hasrun: return Task.ASK_LATER self.add_moc_tasks() return Task.Task.runnable_status(self) def add_moc_tasks(self): """ Create the moc tasks by looking in ``bld.raw_deps[self.uid()]`` """ node = self.inputs[0] bld = self.generator.bld try: # compute the signature once to know if there is a moc file to create self.signature() except KeyError: # the moc file may be referenced somewhere else pass else: # remove the signature, it must be recomputed with the moc task delattr(self, 'cache_sig') moctasks=[] mocfiles=[] try: tmp_lst = bld.raw_deps[self.uid()] bld.raw_deps[self.uid()] = [] except KeyError: tmp_lst = [] for d in tmp_lst: if not d.endswith('.moc'): continue # paranoid check if d in mocfiles: Logs.error("paranoia owns") continue # process that base.moc only once mocfiles.append(d) # find the extension - this search is done only once h_node = None try: ext = Options.options.qt_header_ext.split() except AttributeError: pass if not ext: ext = MOC_H base2 = d[:-4] for x in [node.parent] + self.generator.includes_nodes: for e in ext: h_node = x.find_node(base2 + e) if h_node: break if h_node: m_node = h_node.change_ext('.moc') break else: for k in EXT_QT4: if base2.endswith(k): for x in [node.parent] + self.generator.includes_nodes: h_node = x.find_node(base2) if h_node: break if h_node: m_node = h_node.change_ext(k + '.moc') break if not h_node: raise Errors.WafError('no header found for %r which is a moc file' % d) # next time we will not search for the extension (look at the 'for' loop below) bld.node_deps[(self.inputs[0].parent.abspath(), m_node.name)] = h_node # create the task task = Task.classes['moc'](env=self.env, generator=self.generator) task.set_inputs(h_node) task.set_outputs(m_node) # direct injection in the build phase (safe because called from the main thread) gen = bld.producer gen.outstanding.insert(0, task) gen.total += 1 moctasks.append(task) # remove raw deps except the moc files to save space (optimization) tmp_lst = bld.raw_deps[self.uid()] = mocfiles # look at the file inputs, it is set right above lst = bld.node_deps.get(self.uid(), ()) for d in lst: name = d.name if name.endswith('.moc'): task = Task.classes['moc'](env=self.env, generator=self.generator) task.set_inputs(bld.node_deps[(self.inputs[0].parent.abspath(), name)]) # 1st element in a tuple task.set_outputs(d) gen = bld.producer gen.outstanding.insert(0, task) gen.total += 1 moctasks.append(task) # simple scheduler dependency: run the moc task before others self.run_after.update(set(moctasks)) self.moc_done = 1 run = Task.classes['cxx'].__dict__['run'] class trans_update(Task.Task): """Update a .ts files from a list of C++ files""" run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' color = 'BLUE' Task.update_outputs(trans_update) class XMLHandler(ContentHandler): """ Parser for *.qrc* files """ def __init__(self): self.buf = [] self.files = [] def startElement(self, name, attrs): if name == 'file': self.buf = [] def endElement(self, name): if name == 'file': self.files.append(str(''.join(self.buf))) def characters(self, cars): self.buf.append(cars) @extension(*EXT_RCC) def create_rcc_task(self, node): "Create rcc and cxx tasks for *.qrc* files" rcnode = node.change_ext('_rc.cpp') rcctask = self.create_task('rcc', node, rcnode) cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) try: self.compiled_tasks.append(cpptask) except AttributeError: self.compiled_tasks = [cpptask] return cpptask @extension(*EXT_UI) def create_uic_task(self, node): "hook for uic tasks" uictask = self.create_task('ui4', node) uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])] @extension('.ts') def add_lang(self, node): """add all the .ts file into self.lang""" self.lang = self.to_list(getattr(self, 'lang', [])) + [node] @feature('qt4') @after_method('apply_link') def apply_qt4(self): """ Add MOC_FLAGS which may be necessary for moc:: def build(bld): bld.program(features='qt4', source='main.cpp', target='app', use='QTCORE') The additional parameters are: :param lang: list of translation files (\*.ts) to process :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension :param update: whether to process the C++ files to update the \*.ts files (use **waf --translate**) :type update: bool :param langname: if given, transform the \*.ts files into a .qrc files to include in the binary file :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension """ if getattr(self, 'lang', None): qmtasks = [] for x in self.to_list(self.lang): if isinstance(x, str): x = self.path.find_resource(x + '.ts') qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) if getattr(self, 'update', None) and Options.options.trans_qt4: cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')] for x in qmtasks: self.create_task('trans_update', cxxnodes, x.inputs) if getattr(self, 'langname', None): qmnodes = [x.outputs[0] for x in qmtasks] rcnode = self.langname if isinstance(rcnode, str): rcnode = self.path.find_or_declare(rcnode + '.qrc') t = self.create_task('qm2rcc', qmnodes, rcnode) k = create_rcc_task(self, t.outputs[0]) self.link_task.inputs.append(k.outputs[0]) lst = [] for flag in self.to_list(self.env['CXXFLAGS']): if len(flag) < 2: continue f = flag[0:2] if f in ['-D', '-I', '/D', '/I']: if (f[0] == '/'): lst.append('-' + flag[1:]) else: lst.append(flag) self.env['MOC_FLAGS'] = lst @extension(*EXT_QT4) def cxx_hook(self, node): """ Re-map C++ file extensions to the :py:class:`waflib.Tools.qt4.qxx` task. """ return self.create_compiled_task('qxx', node) class rcc(Task.Task): """ Process *.qrc* files """ color = 'BLUE' run_str = '${QT_RCC} -name ${SRC[0].name} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' ext_out = ['.h'] def scan(self): """Parse the *.qrc* files""" node = self.inputs[0] if not has_xml: Logs.error('no xml support was found, the rcc dependencies will be incomplete!') return ([], []) parser = make_parser() curHandler = XMLHandler() parser.setContentHandler(curHandler) fi = open(self.inputs[0].abspath()) parser.parse(fi) fi.close() nodes = [] names = [] root = self.inputs[0].parent for x in curHandler.files: nd = root.find_resource(x) if nd: nodes.append(nd) else: names.append(x) return (nodes, names) class moc(Task.Task): """ Create *.moc* files """ color = 'BLUE' run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' class ui4(Task.Task): """ Process *.ui* files """ color = 'BLUE' run_str = '${QT_UIC} ${SRC} -o ${TGT}' ext_out = ['.h'] class ts2qm(Task.Task): """ Create *.qm* files from *.ts* files """ color = 'BLUE' run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' class qm2rcc(Task.Task): """ Transform *.qm* files into *.rc* files """ color = 'BLUE' after = 'ts2qm' def run(self): """Create a qrc file including the inputs""" txt = '\n'.join(['%s' % k.path_from(self.outputs[0].parent) for k in self.inputs]) code = '\n\n%s\n\n' % txt self.outputs[0].write(code) def configure(self): """ Besides the configuration options, the environment variable QT4_ROOT may be used to give the location of the qt4 libraries (absolute path). The detection will use the program *pkg-config* through :py:func:`waflib.Tools.config_c.check_cfg` """ self.find_qt4_binaries() self.set_qt4_libs_to_check() self.find_qt4_libraries() self.add_qt4_rpath() self.simplify_qt4_libs() @conf def find_qt4_binaries(self): env = self.env opt = Options.options qtdir = getattr(opt, 'qtdir', '') qtbin = getattr(opt, 'qtbin', '') paths = [] if qtdir: qtbin = os.path.join(qtdir, 'bin') # the qt directory has been given from QT4_ROOT - deduce the qt binary path if not qtdir: qtdir = self.environ.get('QT4_ROOT', '') qtbin = os.path.join(qtdir, 'bin') if qtbin: paths = [qtbin] # no qtdir, look in the path and in /usr/local/Trolltech if not qtdir: paths = os.environ.get('PATH', '').split(os.pathsep) paths.append('/usr/share/qt4/bin/') try: lst = Utils.listdir('/usr/local/Trolltech/') except OSError: pass else: if lst: lst.sort() lst.reverse() # keep the highest version qtdir = '/usr/local/Trolltech/%s/' % lst[0] qtbin = os.path.join(qtdir, 'bin') paths.append(qtbin) # at the end, try to find qmake in the paths given # keep the one with the highest version cand = None prev_ver = ['4', '0', '0'] for qmk in ['qmake-qt4', 'qmake4', 'qmake']: try: qmake = self.find_program(qmk, path_list=paths) except self.errors.ConfigurationError: pass else: try: version = self.cmd_and_log([qmake, '-query', 'QT_VERSION']).strip() except self.errors.ConfigurationError: pass else: if version: new_ver = version.split('.') if new_ver > prev_ver: cand = qmake prev_ver = new_ver if cand: self.env.QMAKE = cand else: self.fatal('Could not find qmake for qt4') qtbin = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_BINS']).strip() + os.sep def find_bin(lst, var): for f in lst: try: ret = self.find_program(f, path_list=paths) except self.errors.ConfigurationError: pass else: env[var]=ret break find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') find_bin(['uic-qt4', 'uic'], 'QT_UIC') if not env['QT_UIC']: self.fatal('cannot find the uic compiler for qt4') try: uicver = self.cmd_and_log(env['QT_UIC'] + " -version 2>&1").strip() except self.errors.ConfigurationError: self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') self.msg('Checking for uic version', '%s' % uicver) if uicver.find(' 3.') != -1: self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') find_bin(['moc-qt4', 'moc'], 'QT_MOC') find_bin(['rcc'], 'QT_RCC') find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE') find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE') env['UIC3_ST']= '%s -o %s' env['UIC_ST'] = '%s -o %s' env['MOC_ST'] = '-o' env['ui_PATTERN'] = 'ui_%s.h' env['QT_LRELEASE_FLAGS'] = ['-silent'] env.MOCCPPPATH_ST = '-I%s' env.MOCDEFINES_ST = '-D%s' @conf def find_qt4_libraries(self): qtlibs = getattr(Options.options, 'qtlibs', '') if not qtlibs: try: qtlibs = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_LIBS']).strip() except Errors.WafError: qtdir = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_PREFIX']).strip() + os.sep qtlibs = os.path.join(qtdir, 'lib') self.msg('Found the Qt4 libraries in', qtlibs) qtincludes = self.cmd_and_log([self.env.QMAKE, '-query', 'QT_INSTALL_HEADERS']).strip() env = self.env if not 'PKG_CONFIG_PATH' in os.environ: os.environ['PKG_CONFIG_PATH'] = '%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib' % (qtlibs, qtlibs) try: self.check_cfg(atleast_pkgconfig_version='0.1') except self.errors.ConfigurationError: for i in self.qt4_vars: uselib = i.upper() if Utils.unversioned_sys_platform() == "darwin": # Since at least qt 4.7.3 each library locates in separate directory frameworkName = i + ".framework" qtDynamicLib = os.path.join(qtlibs, frameworkName, i) if os.path.exists(qtDynamicLib): env.append_unique('FRAMEWORK_' + uselib, i) self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('INCLUDES_' + uselib, os.path.join(qtlibs, frameworkName, 'Headers')) elif sys.platform != "win32": qtDynamicLib = os.path.join(qtlibs, "lib" + i + ".so") qtStaticLib = os.path.join(qtlibs, "lib" + i + ".a") if os.path.exists(qtDynamicLib): env.append_unique('LIB_' + uselib, i) self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') elif os.path.exists(qtStaticLib): env.append_unique('LIB_' + uselib, i) self.msg('Checking for %s' % i, qtStaticLib, 'GREEN') else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) else: # Release library names are like QtCore4 for k in ("lib%s.a", "lib%s4.a", "%s.lib", "%s4.lib"): lib = os.path.join(qtlibs, k % i) if os.path.exists(lib): env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) self.msg('Checking for %s' % i, lib, 'GREEN') break else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) # Debug library names are like QtCore4d uselib = i.upper() + "_debug" for k in ("lib%sd.a", "lib%sd4.a", "%sd.lib", "%sd4.lib"): lib = os.path.join(qtlibs, k % i) if os.path.exists(lib): env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) self.msg('Checking for %s' % i, lib, 'GREEN') break else: self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('LIBPATH_' + uselib, qtlibs) env.append_unique('INCLUDES_' + uselib, qtincludes) env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) else: for i in self.qt4_vars_debug + self.qt4_vars: self.check_cfg(package=i, args='--cflags --libs', mandatory=False) @conf def simplify_qt4_libs(self): # the libpaths make really long command-lines # remove the qtcore ones from qtgui, etc env = self.env def process_lib(vars_, coreval): for d in vars_: var = d.upper() if var == 'QTCORE': continue value = env['LIBPATH_'+var] if value: core = env[coreval] accu = [] for lib in value: if lib in core: continue accu.append(lib) env['LIBPATH_'+var] = accu process_lib(self.qt4_vars, 'LIBPATH_QTCORE') process_lib(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def add_qt4_rpath(self): # rpath if wanted env = self.env if Options.options.want_rpath: def process_rpath(vars_, coreval): for d in vars_: var = d.upper() value = env['LIBPATH_'+var] if value: core = env[coreval] accu = [] for lib in value: if var != 'QTCORE': if lib in core: continue accu.append('-Wl,--rpath='+lib) env['RPATH_'+var] = accu process_rpath(self.qt4_vars, 'LIBPATH_QTCORE') process_rpath(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def set_qt4_libs_to_check(self): if not hasattr(self, 'qt4_vars'): self.qt4_vars = QT4_LIBS self.qt4_vars = Utils.to_list(self.qt4_vars) if not hasattr(self, 'qt4_vars_debug'): self.qt4_vars_debug = [a + '_debug' for a in self.qt4_vars] self.qt4_vars_debug = Utils.to_list(self.qt4_vars_debug) def options(opt): """ Command-line options """ opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') opt.add_option('--header-ext', type='string', default='', help='header extension for moc files', dest='qt_header_ext') for i in 'qtdir qtbin qtlibs'.split(): opt.add_option('--'+i, type='string', default='', dest=i) opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) debian/waf-1.6/waflib/Tools/gxx.py0000664000000000000000000001033712145744415014006 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 """ g++/llvm detection. """ import os, sys from waflib import Configure, Options, Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_gxx(conf): """ Find the program g++, and if present, try to detect its version number """ cxx = conf.find_program(['g++', 'c++'], var='CXX') cxx = conf.cmd_to_list(cxx) conf.get_cc_version(cxx, gcc=True) conf.env.CXX_NAME = 'gcc' conf.env.CXX = cxx @conf def gxx_common_flags(conf): """ Common flags for g++ on nearly all platforms """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-fPIC'] v['LINKFLAGS_cxxshlib'] = ['-shared'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = ['-Wl,-Bstatic'] v['cxxstlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CXXFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conf def gxx_modifier_win32(conf): """Configuration flags for executing gcc on Windows""" v = conf.env v['cxxprogram_PATTERN'] = '%s.exe' v['cxxshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['CXXFLAGS_cxxshlib'] = [] v.append_value('CXXFLAGS_cxxshlib', ['-DDLL_EXPORT']) # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gxx_modifier_cygwin(conf): """Configuration flags for executing g++ on Cygwin""" gxx_modifier_win32(conf) v = conf.env v['cxxshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_cxxshlib', ['-Wl,--enable-auto-image-base']) v['CXXFLAGS_cxxshlib'] = [] @conf def gxx_modifier_darwin(conf): """Configuration flags for executing g++ on MacOS""" v = conf.env v['CXXFLAGS_cxxshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_cxxshlib'] = ['-dynamiclib'] v['cxxshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = ['-framework'] v['ARCH_ST'] = ['-arch'] v['LINKFLAGS_cxxstlib'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] v['SONAME_ST'] = [] @conf def gxx_modifier_aix(conf): """Configuration flags for executing g++ on AIX""" v = conf.env v['LINKFLAGS_cxxprogram']= ['-Wl,-brtl'] v['LINKFLAGS_cxxshlib'] = ['-shared', '-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = [] @conf def gxx_modifier_hpux(conf): v = conf.env v['SHLIB_MARKER'] = [] v['CFLAGS_cxxshlib'] = ['-fPIC','-DPIC'] v['cxxshlib_PATTERN'] = 'lib%s.sl' @conf def gxx_modifier_platform(conf): """Execute platform-specific functions based on *gxx_modifier_+NAME*""" # * set configurations specific for a platform. # * the destination platform is detected automatically by looking at the macros the compiler predefines, # and if it's not recognised, it fallbacks to sys.platform. gxx_modifier_func = getattr(conf, 'gxx_modifier_' + conf.env.DEST_OS, None) if gxx_modifier_func: gxx_modifier_func() def configure(conf): """ Configuration for g++ """ conf.find_gxx() conf.find_ar() conf.gxx_common_flags() conf.gxx_modifier_platform() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/gcc.py0000664000000000000000000001027612145744415013736 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 """ gcc/llvm detection. """ import os, sys from waflib import Configure, Options, Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_gcc(conf): """ Find the program gcc, and if present, try to detect its version number """ cc = conf.find_program(['gcc', 'cc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_cc_version(cc, gcc=True) conf.env.CC_NAME = 'gcc' conf.env.CC = cc @conf def gcc_common_flags(conf): """ Common flags for gcc on nearly all platforms """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Wl,-Bdynamic' v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cprogram_PATTERN'] = '%s' # shared librar v['CFLAGS_cshlib'] = ['-fPIC'] v['LINKFLAGS_cshlib'] = ['-shared'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' # osx stuff v['LINKFLAGS_MACBUNDLE'] = ['-bundle', '-undefined', 'dynamic_lookup'] v['CFLAGS_MACBUNDLE'] = ['-fPIC'] v['macbundle_PATTERN'] = '%s.bundle' @conf def gcc_modifier_win32(conf): """Configuration flags for executing gcc on Windows""" v = conf.env v['cprogram_PATTERN'] = '%s.exe' v['cshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['CFLAGS_cshlib'] = [] v.append_value('CFLAGS_cshlib', ['-DDLL_EXPORT']) # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gcc_modifier_cygwin(conf): """Configuration flags for executing gcc on Cygwin""" gcc_modifier_win32(conf) v = conf.env v['cshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_cshlib', ['-Wl,--enable-auto-image-base']) v['CFLAGS_cshlib'] = [] @conf def gcc_modifier_darwin(conf): """Configuration flags for executing gcc on MacOS""" v = conf.env v['CFLAGS_cshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_cshlib'] = ['-dynamiclib'] v['cshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = ['-framework'] v['ARCH_ST'] = ['-arch'] v['LINKFLAGS_cstlib'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] v['SONAME_ST'] = [] @conf def gcc_modifier_aix(conf): """Configuration flags for executing gcc on AIX""" v = conf.env v['LINKFLAGS_cprogram'] = ['-Wl,-brtl'] v['LINKFLAGS_cshlib'] = ['-shared','-Wl,-brtl,-bexpfull'] v['SHLIB_MARKER'] = [] @conf def gcc_modifier_hpux(conf): v = conf.env v['SHLIB_MARKER'] = [] v['CFLAGS_cshlib'] = ['-fPIC','-DPIC'] v['cshlib_PATTERN'] = 'lib%s.sl' @conf def gcc_modifier_platform(conf): """Execute platform-specific functions based on *gcc_modifier_+NAME*""" # * set configurations specific for a platform. # * the destination platform is detected automatically by looking at the macros the compiler predefines, # and if it's not recognised, it fallbacks to sys.platform. gcc_modifier_func = getattr(conf, 'gcc_modifier_' + conf.env.DEST_OS, None) if gcc_modifier_func: gcc_modifier_func() def configure(conf): """ Configuration for gcc """ conf.find_gcc() conf.find_ar() conf.gcc_common_flags() conf.gcc_modifier_platform() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/flex.py0000664000000000000000000000177312145744415014142 0ustar #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy, 2006-2010 (ita) """ The **flex** program is a code generator which creates C or C++ files. The generated files are compiled into object files. """ import waflib.TaskGen def decide_ext(self, node): if 'cxx' in self.features: return ['.lex.cc'] return ['.lex.c'] def flexfun(tsk): env = tsk.env bld = tsk.generator.bld wd = bld.variant_dir def to_list(xx): if isinstance(xx, str): return [xx] return xx tsk.last_cmd = lst = [] lst.extend(to_list(env['FLEX'])) lst.extend(to_list(env['FLEXFLAGS'])) lst.extend([a.path_from(bld.bldnode) for a in tsk.inputs]) lst = [x for x in lst if x] txt = bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) tsk.outputs[0].write(txt) waflib.TaskGen.declare_chain( name = 'flex', rule = flexfun, # issue #854 ext_in = '.l', decider = decide_ext, ) def configure(conf): """ Detect the *flex* program """ conf.find_program('flex', var='FLEX') conf.env.FLEXFLAGS = ['-t'] debian/waf-1.6/waflib/Tools/ifort.py0000664000000000000000000000265412145744415014326 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf @conf def find_ifort(conf): fc = conf.find_program('ifort', var='FC') fc = conf.cmd_to_list(fc) conf.get_ifort_version(fc) conf.env.FC_NAME = 'IFORT' @conf def ifort_modifier_cygwin(conf): raise NotImplementedError("Ifort on cygwin not yet implemented") @conf def ifort_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def ifort_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def ifort_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() ifort_modifier_func = getattr(conf, 'ifort_modifier_' + dest_os, None) if ifort_modifier_func: ifort_modifier_func() @conf def get_ifort_version(conf, fc): """get the compiler version""" version_re = re.compile(r"ifort\s*\(IFORT\)\s*(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('cannot determine ifort version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_ifort() conf.find_program('xiar', var='AR') conf.env.ARFLAGS = 'rcs' conf.fc_flags() conf.ifort_modifier_platform() debian/waf-1.6/waflib/Tools/gdc.py0000664000000000000000000000216112145744415013731 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) import sys from waflib.Tools import ar, d from waflib.Configure import conf @conf def find_gdc(conf): """ Find the program gdc and set the variable *D* """ conf.find_program('gdc', var='D') @conf def common_flags_gdc(conf): """ Set the flags required by *gdc* """ v = conf.env # _DFLAGS _DIMPORTFLAGS # for mory info about the meaning of this dict see dmd.py v['DFLAGS'] = [] v['D_SRC_F'] = ['-c'] v['D_TGT_F'] = '-o%s' # linker v['D_LINKER'] = v['D'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-o%s' v['DINC_ST'] = '-I%s' v['DSHLIB_MARKER'] = v['DSTLIB_MARKER'] = '' v['DSTLIB_ST'] = v['DSHLIB_ST'] = '-l%s' v['DSTLIBPATH_ST'] = v['DLIBPATH_ST'] = '-L%s' v['LINKFLAGS_dshlib'] = ['-shared'] v['DHEADER_ext'] = '.di' v.DFLAGS_d_with_header = '-fintfc' v['D_HDR_F'] = '-fintfc-file=%s' def configure(conf): """ Configuration for gdc """ conf.find_gdc() conf.load('ar') conf.load('d') conf.common_flags_gdc() conf.d_platform_flags() debian/waf-1.6/waflib/Tools/xlc.py0000664000000000000000000000311412145744415013761 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_xlc(conf): """ Detect the Aix C compiler """ cc = conf.find_program(['xlc_r', 'xlc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_xlc_version(cc) conf.env.CC_NAME = 'xlc' conf.env.CC = cc @conf def xlc_common_flags(conf): """ Flags required for executing the Aix C compiler """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] # program v['LINKFLAGS_cprogram'] = ['-Wl,-brtl'] v['cprogram_PATTERN'] = '%s' # shared library v['CFLAGS_cshlib'] = ['-fPIC'] v['LINKFLAGS_cshlib'] = ['-G', '-Wl,-brtl,-bexpfull'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = [] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_xlc() conf.find_ar() conf.xlc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/tex.py0000664000000000000000000002656212145744415014007 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ TeX/LaTeX/PDFLaTeX/XeLaTeX support Example:: def configure(conf): conf.load('tex') if not conf.env.LATEX: conf.fatal('The program LaTex is required') def build(bld): bld( features = 'tex', type = 'latex', # pdflatex or xelatex source = 'document.ltx', # mandatory, the source outs = 'ps', # 'pdf' or 'ps pdf' deps = 'crossreferencing.lst', # to give dependencies directly prompt = 1, # 0 for the batch mode ) To configure with a special program use:: $ PDFLATEX=luatex waf configure """ import os, re from waflib import Utils, Task, Errors from waflib.TaskGen import feature, before_method from waflib.Logs import error, warn, debug re_bibunit = re.compile(r'\\(?Pputbib)\[(?P[^\[\]]*)\]',re.M) def bibunitscan(self): """ Parse the inputs and try to find the *bibunit* dependencies :return: list of bibunit files :rtype: list of :py:class:`waflib.Node.Node` """ node = self.inputs[0] nodes = [] if not node: return nodes code = Utils.readf(node.abspath()) for match in re_bibunit.finditer(code): path = match.group('file') if path: for k in ['', '.bib']: # add another loop for the tex include paths? debug('tex: trying %s%s' % (path, k)) fi = node.parent.find_resource(path + k) if fi: nodes.append(fi) # no break, people are crazy else: debug('tex: could not find %s' % path) debug("tex: found the following bibunit files: %s" % nodes) return nodes exts_deps_tex = ['', '.ltx', '.tex', '.bib', '.pdf', '.png', '.eps', '.ps'] """List of typical file extensions included in latex files""" exts_tex = ['.ltx', '.tex'] """List of typical file extensions that contain latex""" re_tex = re.compile(r'\\(?Pinclude|bibliography|putbib|includegraphics|input|import|bringin|lstinputlisting)(\[[^\[\]]*\])?{(?P[^{}]*)}',re.M) """Regexp for expressions that may include latex files""" g_bibtex_re = re.compile('bibdata', re.M) """Regexp for bibtex files""" class tex(Task.Task): """ Compile a tex/latex file. .. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex """ bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False) bibtex_fun.__doc__ = """ Execute the program **bibtex** """ makeindex_fun, _ = Task.compile_fun('${MAKEINDEX} ${MAKEINDEXFLAGS} ${SRCFILE}', shell=False) makeindex_fun.__doc__ = """ Execute the program **makeindex** """ def scan_aux(self, node): """ A recursive regex-based scanner that finds included auxiliary files. """ nodes = [node] re_aux = re.compile(r'\\@input{(?P[^{}]*)}', re.M) def parse_node(node): code = node.read() for match in re_aux.finditer(code): path = match.group('file') found = node.parent.find_or_declare(path) if found and found not in nodes: debug('tex: found aux node ' + found.abspath()) nodes.append(found) parse_node(found) parse_node(node) return nodes def scan(self): """ A recursive regex-based scanner that finds latex dependencies. It uses :py:attr:`waflib.Tools.tex.re_tex` Depending on your needs you might want: * to change re_tex:: from waflib.Tools import tex tex.re_tex = myregex * or to change the method scan from the latex tasks:: from waflib.Task import classes classes['latex'].scan = myscanfunction """ node = self.inputs[0] nodes = [] names = [] seen = [] if not node: return (nodes, names) def parse_node(node): if node in seen: return seen.append(node) code = node.read() global re_tex for match in re_tex.finditer(code): for path in match.group('file').split(','): if path: add_name = True found = None for k in exts_deps_tex: debug('tex: trying %s%s' % (path, k)) found = node.parent.find_resource(path + k) if found and not found in self.outputs: nodes.append(found) add_name = False for ext in exts_tex: if found.name.endswith(ext): parse_node(found) break # no break, people are crazy if add_name: names.append(path) parse_node(node) for x in nodes: x.parent.get_bld().mkdir() debug("tex: found the following : %s and names %s" % (nodes, names)) return (nodes, names) def check_status(self, msg, retcode): """ Check an exit status and raise an error with a particular message :param msg: message to display if the code is non-zero :type msg: string :param retcode: condition :type retcode: boolean """ if retcode != 0: raise Errors.WafError("%r command exit status %r" % (msg, retcode)) def bibfile(self): """ Parse the *.aux* files to find a bibfile to process. If yes, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun` """ need_bibtex = False try: for aux_node in self.aux_nodes: ct = aux_node.read() if g_bibtex_re.findall(ct): need_bibtex = True break except (OSError, IOError): error('error bibtex scan') else: # only the main .aux file needs to be processed if need_bibtex: warn('calling bibtex') self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS}) self.env.SRCFILE = self.aux_nodes[0].name[:-4] self.check_status('error when calling bibtex', self.bibtex_fun()) def bibunits(self): """ Parse the *.aux* file to find bibunit files. If there are bibunit files, execute :py:meth:`waflib.Tools.tex.tex.bibtex_fun`. """ try: bibunits = bibunitscan(self) except FSError: error('error bibunitscan') else: if bibunits: fn = ['bu' + str(i) for i in xrange(1, len(bibunits) + 1)] if fn: warn('calling bibtex on bibunits') for f in fn: self.env.env = {'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS} self.env.SRCFILE = f self.check_status('error when calling bibtex', self.bibtex_fun()) def makeindex(self): """ Look on the filesystem if there is a *.idx* file to process. If yes, execute :py:meth:`waflib.Tools.tex.tex.makeindex_fun` """ try: idx_path = self.idx_node.abspath() os.stat(idx_path) except OSError: warn('index file %s absent, not calling makeindex' % idx_path) else: warn('calling makeindex') self.env.SRCFILE = self.idx_node.name self.env.env = {} self.check_status('error when calling makeindex %s' % idx_path, self.makeindex_fun()) def run(self): """ Runs the TeX build process. It may require multiple passes, depending on the usage of cross-references, bibliographies, content susceptible of needing such passes. The appropriate TeX compiler is called until the *.aux* files stop changing. Makeindex and bibtex are called if necessary. """ env = self.env if not env['PROMPT_LATEX']: env.append_value('LATEXFLAGS', '-interaction=batchmode') env.append_value('PDFLATEXFLAGS', '-interaction=batchmode') env.append_value('XELATEXFLAGS', '-interaction=batchmode') fun = self.texfun node = self.inputs[0] srcfile = node.abspath() texinputs = self.env.TEXINPUTS or '' self.TEXINPUTS = node.parent.get_bld().abspath() + os.pathsep + node.parent.get_src().abspath() + os.pathsep + texinputs + os.pathsep self.aux_node = node.change_ext('.aux') # TODO waf 1.7 remove (left for compatibility) # important, set the cwd for everybody self.cwd = self.inputs[0].parent.get_bld().abspath() warn('first pass on %s' % self.__class__.__name__) self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'TEXINPUTS': self.TEXINPUTS}) self.env.SRCFILE = srcfile self.check_status('error when calling latex', fun()) self.aux_nodes = self.scan_aux(node.change_ext('.aux')) self.idx_node = node.change_ext('.idx') self.bibfile() self.bibunits() self.makeindex() hash = '' for i in range(10): # prevent against infinite loops - one never knows # watch the contents of file.aux and stop if file.aux does not change anymore prev_hash = hash try: hashes = [Utils.h_file(x.abspath()) for x in self.aux_nodes] hash = Utils.h_list(hashes) except (OSError, IOError): error('could not read aux.h') pass if hash and hash == prev_hash: break # run the command warn('calling %s' % self.__class__.__name__) self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'TEXINPUTS': self.TEXINPUTS}) self.env.SRCFILE = srcfile self.check_status('error when calling %s' % self.__class__.__name__, fun()) class latex(tex): texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) class pdflatex(tex): texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) class xelatex(tex): texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) class dvips(Task.Task): run_str = '${DVIPS} ${DVIPSFLAGS} ${SRC} -o ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] class dvipdf(Task.Task): run_str = '${DVIPDF} ${DVIPDFFLAGS} ${SRC} ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] class pdf2ps(Task.Task): run_str = '${PDF2PS} ${PDF2PSFLAGS} ${SRC} ${TGT}' color = 'BLUE' after = ['latex', 'pdflatex', 'xelatex'] @feature('tex') @before_method('process_source') def apply_tex(self): """ Create :py:class:`waflib.Tools.tex.tex` objects, and dvips/dvipdf/pdf2ps tasks if necessary (outs='ps', etc). """ if not getattr(self, 'type', None) in ['latex', 'pdflatex', 'xelatex']: self.type = 'pdflatex' tree = self.bld outs = Utils.to_list(getattr(self, 'outs', [])) # prompt for incomplete files (else the batchmode is used) self.env['PROMPT_LATEX'] = getattr(self, 'prompt', 1) deps_lst = [] if getattr(self, 'deps', None): deps = self.to_list(self.deps) for filename in deps: n = self.path.find_resource(filename) if not n in deps_lst: deps_lst.append(n) for node in self.to_nodes(self.source): if self.type == 'latex': task = self.create_task('latex', node, node.change_ext('.dvi')) elif self.type == 'pdflatex': task = self.create_task('pdflatex', node, node.change_ext('.pdf')) elif self.type == 'xelatex': task = self.create_task('xelatex', node, node.change_ext('.pdf')) task.env = self.env # add the manual dependencies if deps_lst: try: lst = tree.node_deps[task.uid()] for n in deps_lst: if not n in lst: lst.append(n) except KeyError: tree.node_deps[task.uid()] = deps_lst if self.type == 'latex': if 'ps' in outs: tsk = self.create_task('dvips', task.outputs, node.change_ext('.ps')) tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.get_bld().abspath()} if 'pdf' in outs: tsk = self.create_task('dvipdf', task.outputs, node.change_ext('.pdf')) tsk.env.env = {'TEXINPUTS' : node.parent.abspath() + os.pathsep + self.path.abspath() + os.pathsep + self.path.get_bld().abspath()} elif self.type == 'pdflatex': if 'ps' in outs: self.create_task('pdf2ps', task.outputs, node.change_ext('.ps')) self.source = [] def configure(self): """ Try to find the programs tex, latex and others. Do not raise any error if they are not found. """ v = self.env for p in 'tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): try: self.find_program(p, var=p.upper()) except self.errors.ConfigurationError: pass v['DVIPSFLAGS'] = '-Ppdf' debian/waf-1.6/waflib/Tools/vala.py0000664000000000000000000002542512145744415014127 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 # Radosław Szkodziński, 2010 """ At this point, vala is still unstable, so do not expect this tool to be too stable either (apis, etc) """ import os.path, shutil, re from waflib import Context, Task, Utils, Logs, Options, Errors from waflib.TaskGen import extension from waflib.Configure import conf class valac(Task.Task): """ Task to compile vala files. """ vars = ["VALAC", "VALAC_VERSION", "VALAFLAGS"] ext_out = ['.h'] def run(self): env = self.env cmd = [env['VALAC'], '-C', '--quiet'] cmd.extend(Utils.to_list(env['VALAFLAGS'])) if self.threading: cmd.append('--thread') if self.profile: cmd.append('--profile=%s' % self.profile) if self.target_glib: cmd.append('--target-glib=%s' % self.target_glib) if self.is_lib: cmd.append('--library=' + self.target) for x in self.outputs: if x.name.endswith('.h'): cmd.append('--header=' + x.name) if self.gir: cmd.append('--gir=%s.gir' % self.gir) for vapi_dir in self.vapi_dirs: cmd.append('--vapidir=%s' % vapi_dir) for package in self.packages: cmd.append('--pkg=%s' % package) for package in self.packages_private: cmd.append('--pkg=%s' % package) for define in self.vala_defines: cmd.append('--define=%s' % define) cmd.extend([a.abspath() for a in self.inputs]) ret = self.exec_command(cmd, cwd=self.outputs[0].parent.abspath()) if ret: return ret for x in self.outputs: if id(x.parent) != id(self.outputs[0].parent): shutil.move(self.outputs[0].parent.abspath() + os.sep + x.name, x.abspath()) if self.packages and getattr(self, 'deps_node', None): self.deps_node.write('\n'.join(self.packages)) return ret @extension('.vala', '.gs') def vala_file(self, node): """ Compile a vala file and bind the task to *self.valatask*. If an existing vala task is already set, add the node to its inputs. The typical example is:: def build(bld): bld.program( packages = 'gtk+-2.0', target = 'vala-gtk-example', uselib = 'GTK GLIB', source = 'vala-gtk-example.vala foo.vala', vala_defines = ['DEBUG'] # the following arguments are for libraries #gir = 'hello-1.0', #gir_path = '/tmp', #vapi_path = '/tmp', #pkg_name = 'hello' # disable installing of gir, vapi and header #install_binding = False ) :param node: vala file :type node: :py:class:`waflib.Node.Node` """ # TODO: the vala task should use self.generator.attribute instead of copying attributes from self to the task valatask = getattr(self, "valatask", None) # there is only one vala task and it compiles all vala files .. :-/ if not valatask: def _get_api_version(): api_version = '1.0' if hasattr(Context.g_module, 'API_VERSION'): version = Context.g_module.API_VERSION.split(".") if version[0] == "0": api_version = "0." + version[1] else: api_version = version[0] + ".0" return api_version valatask = self.create_task('valac') self.valatask = valatask # this assumes one vala task by task generator self.includes = Utils.to_list(getattr(self, 'includes', [])) self.uselib = self.to_list(getattr(self, 'uselib', [])) valatask.packages = [] valatask.packages_private = Utils.to_list(getattr(self, 'packages_private', [])) valatask.vapi_dirs = [] valatask.target = self.target valatask.threading = False valatask.install_path = getattr(self, 'install_path', '') valatask.profile = getattr(self, 'profile', 'gobject') valatask.vala_defines = getattr(self, 'vala_defines', []) valatask.target_glib = None valatask.gir = getattr(self, 'gir', None) valatask.gir_path = getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0') valatask.vapi_path = getattr(self, 'vapi_path', '${DATAROOTDIR}/vala/vapi') valatask.pkg_name = getattr(self, 'pkg_name', self.env['PACKAGE']) valatask.header_path = getattr(self, 'header_path', '${INCLUDEDIR}/%s-%s' % (valatask.pkg_name, _get_api_version())) valatask.install_binding = getattr(self, 'install_binding', True) valatask.is_lib = False if not 'cprogram' in self.features: valatask.is_lib = True packages = Utils.to_list(getattr(self, 'packages', [])) vapi_dirs = Utils.to_list(getattr(self, 'vapi_dirs', [])) includes = [] if hasattr(self, 'use'): local_packages = Utils.to_list(self.use)[:] # make sure to have a copy seen = [] while len(local_packages) > 0: package = local_packages.pop() if package in seen: continue seen.append(package) # check if the package exists try: package_obj = self.bld.get_tgen_by_name(package) except Errors.WafError: continue package_name = package_obj.target package_node = package_obj.path package_dir = package_node.path_from(self.path) for task in package_obj.tasks: for output in task.outputs: if output.name == package_name + ".vapi": valatask.set_run_after(task) if package_name not in packages: packages.append(package_name) if package_dir not in vapi_dirs: vapi_dirs.append(package_dir) if package_dir not in includes: includes.append(package_dir) if hasattr(package_obj, 'use'): lst = self.to_list(package_obj.use) lst.reverse() local_packages = [pkg for pkg in lst if pkg not in seen] + local_packages valatask.packages = packages for vapi_dir in vapi_dirs: try: valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).abspath()) valatask.vapi_dirs.append(self.path.find_dir(vapi_dir).get_bld().abspath()) except AttributeError: Logs.warn("Unable to locate Vala API directory: '%s'" % vapi_dir) self.includes.append(self.bld.srcnode.abspath()) self.includes.append(self.bld.bldnode.abspath()) for include in includes: try: self.includes.append(self.path.find_dir(include).abspath()) self.includes.append(self.path.find_dir(include).get_bld().abspath()) except AttributeError: Logs.warn("Unable to locate include directory: '%s'" % include) if valatask.profile == 'gobject': if hasattr(self, 'target_glib'): Logs.warn('target_glib on vala tasks is not supported --vala-target-glib=MAJOR.MINOR from the vala tool options') if getattr(Options.options, 'vala_target_glib', None): valatask.target_glib = Options.options.vala_target_glib if not 'GOBJECT' in self.uselib: self.uselib.append('GOBJECT') if hasattr(self, 'threading'): if valatask.profile == 'gobject': valatask.threading = self.threading if not 'GTHREAD' in self.uselib: self.uselib.append('GTHREAD') else: #Vala doesn't have threading support for dova nor posix Logs.warn("Profile %s does not have threading support" % valatask.profile) if valatask.is_lib: valatask.outputs.append(self.path.find_or_declare('%s.h' % self.target)) valatask.outputs.append(self.path.find_or_declare('%s.vapi' % self.target)) if valatask.gir: valatask.outputs.append(self.path.find_or_declare('%s.gir' % self.gir)) if valatask.packages: d = self.path.find_or_declare('%s.deps' % self.target) valatask.outputs.append(d) valatask.deps_node = d valatask.inputs.append(node) c_node = node.change_ext('.c') valatask.outputs.append(c_node) self.source.append(c_node) if valatask.is_lib and valatask.install_binding: headers_list = [o for o in valatask.outputs if o.suffix() == ".h"] try: self.install_vheader.source = headers_list except AttributeError: self.install_vheader = self.bld.install_files(valatask.header_path, headers_list, self.env) vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))] try: self.install_vapi.source = vapi_list except AttributeError: self.install_vapi = self.bld.install_files(valatask.vapi_path, vapi_list, self.env) gir_list = [o for o in valatask.outputs if o.suffix() == ".gir"] try: self.install_gir.source = gir_list except AttributeError: self.install_gir = self.bld.install_files(valatask.gir_path, gir_list, self.env) valac = Task.update_outputs(valac) # no decorators for python2 classes @conf def find_valac(self, valac_name, min_version): """ Find the valac program, and execute it to store the version number in *conf.env.VALAC_VERSION* :param valac_name: program name :type valac_name: string or list of string :param min_version: minimum version acceptable :type min_version: tuple of int """ valac = self.find_program(valac_name, var='VALAC') try: output = self.cmd_and_log(valac + ' --version') except Exception: valac_version = None else: ver = re.search(r'\d+.\d+.\d+', output).group(0).split('.') valac_version = tuple([int(x) for x in ver]) self.msg('Checking for %s version >= %r' % (valac_name, min_version), valac_version, valac_version and valac_version >= min_version) if valac and valac_version < min_version: self.fatal("%s version %r is too old, need >= %r" % (valac_name, valac_version, min_version)) self.env['VALAC_VERSION'] = valac_version return valac @conf def check_vala(self, min_version=(0,8,0), branch=None): """ Check if vala compiler from a given branch exists of at least a given version. :param min_version: minimum version acceptable (0.8.0) :type min_version: tuple :param branch: first part of the version number, in case a snapshot is used (0, 8) :type branch: tuple of int """ if not branch: branch = min_version[:2] try: find_valac(self, 'valac-%d.%d' % (branch[0], branch[1]), min_version) except self.errors.ConfigurationError: find_valac(self, 'valac', min_version) @conf def check_vala_deps(self): """ Load the gobject and gthread packages if they are missing. """ if not self.env['HAVE_GOBJECT']: pkg_args = {'package': 'gobject-2.0', 'uselib_store': 'GOBJECT', 'args': '--cflags --libs'} if getattr(Options.options, 'vala_target_glib', None): pkg_args['atleast_version'] = Options.options.vala_target_glib self.check_cfg(**pkg_args) if not self.env['HAVE_GTHREAD']: pkg_args = {'package': 'gthread-2.0', 'uselib_store': 'GTHREAD', 'args': '--cflags --libs'} if getattr(Options.options, 'vala_target_glib', None): pkg_args['atleast_version'] = Options.options.vala_target_glib self.check_cfg(**pkg_args) def configure(self): """ Use the following to enforce minimum vala version:: def configure(conf): conf.load('vala', funs='') conf.check_vala(min_version=(0,10,0)) """ self.load('gnu_dirs') self.check_vala_deps() self.check_vala() def options(opt): """ Load the :py:mod:`waflib.Tools.gnu_dirs` tool and add the ``--vala-target-glib`` command-line option """ opt.load('gnu_dirs') valaopts = opt.add_option_group('Vala Compiler Options') valaopts.add_option ('--vala-target-glib', default=None, dest='vala_target_glib', metavar='MAJOR.MINOR', help='Target version of glib for Vala GObject code generation') debian/waf-1.6/waflib/Tools/perl.py0000664000000000000000000001065612145744415014146 0ustar #!/usr/bin/env python # encoding: utf-8 # andersg at 0x63.nu 2007 # Thomas Nagy 2010 (ita) """ Support for Perl extensions. A C/C++ compiler is required:: def options(opt): opt.load('compiler_c perl') def configure(conf): conf.load('compiler_c perl') conf.check_perl_version((5,6,0)) conf.check_perl_ext_devel() conf.check_perl_module('Cairo') conf.check_perl_module('Devel::PPPort 4.89') def build(bld): bld( features = 'c cshlib perlext', source = 'Mytest.xs', target = 'Mytest', install_path = '${ARCHDIR_PERL}/auto') bld.install_files('${ARCHDIR_PERL}', 'Mytest.pm') """ import os from waflib import Task, Options, Utils from waflib.Configure import conf from waflib.TaskGen import extension, feature, before_method @before_method('apply_incpaths', 'apply_link', 'propagate_uselib_vars') @feature('perlext') def init_perlext(self): """ Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the *lib* prefix from library names. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PERLEXT' in self.uselib: self.uselib.append('PERLEXT') self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['perlext_PATTERN'] @extension('.xs') def xsubpp_file(self, node): """ Create :py:class:`waflib.Tools.perl.xsubpp` tasks to process *.xs* files """ outnode = node.change_ext('.c') self.create_task('xsubpp', node, outnode) self.source.append(outnode) class xsubpp(Task.Task): """ Process *.xs* files """ run_str = '${PERL} ${XSUBPP} -noprototypes -typemap ${EXTUTILS_TYPEMAP} ${SRC} > ${TGT}' color = 'BLUE' ext_out = ['.h'] @conf def check_perl_version(self, minver=None): """ Check if Perl is installed, and set the variable PERL. minver is supposed to be a tuple """ res = True if minver: cver = '.'.join(map(str,minver)) else: cver = '' self.start_msg('Checking for minimum perl version %s' % cver) perl = getattr(Options.options, 'perlbinary', None) if not perl: perl = self.find_program('perl', var='PERL') if not perl: self.end_msg("Perl not found", color="YELLOW") return False self.env['PERL'] = perl version = self.cmd_and_log([perl, "-e", 'printf \"%vd\", $^V']) if not version: res = False version = "Unknown" elif not minver is None: ver = tuple(map(int, version.split("."))) if ver < minver: res = False self.end_msg(version, color=res and "GREEN" or "YELLOW") return res @conf def check_perl_module(self, module): """ Check if specified perlmodule is installed. The minimum version can be specified by specifying it after modulename like this:: def configure(conf): conf.check_perl_module("Some::Module 2.92") """ cmd = [self.env['PERL'], '-e', 'use %s' % module] self.start_msg('perl module %s' % module) try: r = self.cmd_and_log(cmd) except: self.end_msg(False) return None self.end_msg(r or True) return r @conf def check_perl_ext_devel(self): """ Check for configuration needed to build perl extensions. Sets different xxx_PERLEXT variables in the environment. Also sets the ARCHDIR_PERL variable useful as installation path, which can be overridden by ``--with-perl-archdir`` option. """ env = self.env perl = env.PERL if not perl: self.fatal('find perl first') def read_out(cmd): return Utils.to_list(self.cmd_and_log(perl + cmd)) env['LINKFLAGS_PERLEXT'] = read_out(" -MConfig -e'print $Config{lddlflags}'") env['INCLUDES_PERLEXT'] = read_out(" -MConfig -e'print \"$Config{archlib}/CORE\"'") env['CFLAGS_PERLEXT'] = read_out(" -MConfig -e'print \"$Config{ccflags} $Config{cccdlflags}\"'") env['XSUBPP'] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/xsubpp$Config{exe_ext}\"'") env['EXTUTILS_TYPEMAP'] = read_out(" -MConfig -e'print \"$Config{privlib}/ExtUtils/typemap\"'") if not getattr(Options.options, 'perlarchdir', None): env['ARCHDIR_PERL'] = self.cmd_and_log(perl + " -MConfig -e'print $Config{sitearch}'") else: env['ARCHDIR_PERL'] = getattr(Options.options, 'perlarchdir') env['perlext_PATTERN'] = '%s.' + self.cmd_and_log(perl + " -MConfig -e'print $Config{dlext}'") def options(opt): """ Add the ``--with-perl-archdir`` and ``--with-perl-binary`` command-line options. """ opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) debian/waf-1.6/waflib/Tools/bison.py0000664000000000000000000000225512145744415014312 0ustar #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 # Thomas Nagy 2009-2010 (ita) """ The **bison** program is a code generator which creates C or C++ files. The generated files are compiled into object files. """ from waflib import Task from waflib.TaskGen import extension class bison(Task.Task): """Compile bison files""" color = 'BLUE' run_str = '${BISON} ${BISONFLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}' ext_out = ['.h'] # just to make sure @extension('.y', '.yc', '.yy') def big_bison(self, node): """ Create a bison task, which must be executed from the directory of the output file. """ has_h = '-d' in self.env['BISONFLAGS'] outs = [] if node.name.endswith('.yc'): outs.append(node.change_ext('.tab.cc')) if has_h: outs.append(node.change_ext('.tab.hh')) else: outs.append(node.change_ext('.tab.c')) if has_h: outs.append(node.change_ext('.tab.h')) tsk = self.create_task('bison', node, outs) tsk.cwd = node.parent.get_bld().abspath() # and the c/cxx file must be compiled too self.source.append(outs[0]) def configure(conf): """ Detect the *bison* program """ conf.find_program('bison', var='BISON') conf.env.BISONFLAGS = ['-d'] debian/waf-1.6/waflib/Tools/compiler_cxx.py0000664000000000000000000000602312145744415015671 0ustar #!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de 2007 (pmarat) """ Try to detect a C++ compiler from the list of supported compilers (g++, msvc, etc):: def options(opt): opt.load('compiler_cxx') def configure(cnf): cnf.load('compiler_cxx') def build(bld): bld.program(source='main.cpp', target='app') The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_cxx.cxx_compiler`. To register a new C++ compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: def options(opt): opt.load('compiler_cxx') def configure(cnf): from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] cnf.load('compiler_cxx') def build(bld): bld.program(source='main.c', target='app') Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: $ CXX=clang waf configure """ import os, sys, imp, types from waflib.Tools import ccroot from waflib import Utils, Configure from waflib.Logs import debug cxx_compiler = { 'win32': ['msvc', 'g++'], 'cygwin': ['g++'], 'darwin': ['g++'], 'aix': ['xlc++', 'g++'], 'linux': ['g++', 'icpc'], 'sunos': ['sunc++', 'g++'], 'irix': ['g++'], 'hpux': ['g++'], 'gnu': ['g++'], 'java': ['g++', 'msvc', 'icpc'], 'default': ['g++'] } """ Dict mapping the platform names to waf tools finding specific compilers:: from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['linux'] = ['gxx', 'icpc', 'suncxx'] """ def configure(conf): """ Try to find a suitable C++ compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_cxx_compiler except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_cxx')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (c++ compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_cxx: %r' % e) else: if conf.env['CXX']: conf.end_msg(conf.env.get_flat('CXX')) conf.env['COMPILER_CXX'] = compiler break conf.end_msg(False) else: conf.fatal('could not configure a c++ compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-cxx-compiler=gxx """ opt.load_special_tools('cxx_*.py') global cxx_compiler build_platform = Utils.unversioned_sys_platform() possible_compiler_list = cxx_compiler[build_platform in cxx_compiler and build_platform or 'default'] test_for_compiler = ' '.join(possible_compiler_list) cxx_compiler_opts = opt.add_option_group('C++ Compiler Options') cxx_compiler_opts.add_option('--check-cxx-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C++ Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_cxx_compiler") for x in test_for_compiler.split(): opt.load('%s' % x) debian/waf-1.6/waflib/Tools/compiler_c.py0000664000000000000000000000575112145744415015320 0ustar #!/usr/bin/env python # encoding: utf-8 # Matthias Jahn jahn dôt matthias ât freenet dôt de, 2007 (pmarat) """ Try to detect a C compiler from the list of supported compilers (gcc, msvc, etc):: def options(opt): opt.load('compiler_c') def configure(cnf): cnf.load('compiler_c') def build(bld): bld.program(source='main.c', target='app') The compilers are associated to platforms in :py:attr:`waflib.Tools.compiler_c.c_compiler`. To register a new C compiler named *cfoo* (assuming the tool ``waflib/extras/cfoo.py`` exists), use:: def options(opt): opt.load('compiler_c') def configure(cnf): from waflib.Tools.compiler_c import c_compiler c_compiler['win32'] = ['cfoo', 'msvc', 'gcc'] cnf.load('compiler_c') def build(bld): bld.program(source='main.c', target='app') Not all compilers need to have a specific tool. For example, the clang compilers can be detected by the gcc tools when using:: $ CC=clang waf configure """ import os, sys, imp, types from waflib.Tools import ccroot from waflib import Utils, Configure from waflib.Logs import debug c_compiler = { 'win32': ['msvc', 'gcc'], 'cygwin': ['gcc'], 'darwin': ['gcc'], 'aix': ['xlc', 'gcc'], 'linux': ['gcc', 'icc'], 'sunos': ['suncc', 'gcc'], 'irix': ['gcc', 'irixcc'], 'hpux': ['gcc'], 'gnu': ['gcc'], 'java': ['gcc', 'msvc', 'icc'], 'default':['gcc'], } """ Dict mapping the platform names to waf tools finding specific compilers:: from waflib.Tools.compiler_c import c_compiler c_compiler['linux'] = ['gcc', 'icc', 'suncc'] """ def configure(conf): """ Try to find a suitable C compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_c_compiler except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_c')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (c compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_c: %r' % e) else: if conf.env['CC']: conf.end_msg(conf.env.get_flat('CC')) conf.env['COMPILER_CC'] = compiler break conf.end_msg(False) else: conf.fatal('could not configure a c compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-c-compiler=gcc """ opt.load_special_tools('c_*.py', ban=['c_dumbpreproc.py']) global c_compiler build_platform = Utils.unversioned_sys_platform() possible_compiler_list = c_compiler[build_platform in c_compiler and build_platform or 'default'] test_for_compiler = ' '.join(possible_compiler_list) cc_compiler_opts = opt.add_option_group("C Compiler Options") cc_compiler_opts.add_option('--check-c-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following C-Compiler will be checked by default: "%s"' % (build_platform, test_for_compiler), dest="check_c_compiler") for x in test_for_compiler.split(): opt.load('%s' % x) debian/waf-1.6/waflib/Tools/python.py0000664000000000000000000004065012145744415014522 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) # Gustavo Carneiro (gjc), 2007 """ Support for Python, detect the headers and libraries and provide *use* variables to link C/C++ programs against them:: def options(opt): opt.load('compiler_c python') def configure(conf): conf.load('compiler_c python') conf.check_python_version((2,4,2)) conf.check_python_headers() def build(bld): bld.program(features='pyembed', source='a.c', target='myprog') bld.shlib(features='pyext', source='b.c', target='mylib') """ import os, sys from waflib import Utils, Options, Errors from waflib.Logs import debug, warn, info, error from waflib.TaskGen import extension, before_method, after_method, feature from waflib.Configure import conf FRAG = ''' #include #ifdef __cplusplus extern "C" { #endif void Py_Initialize(void); void Py_Finalize(void); #ifdef __cplusplus } #endif int main() { Py_Initialize(); Py_Finalize(); return 0; } ''' """ Piece of C/C++ code used in :py:func:`waflib.Tools.python.check_python_headers` """ INST = ''' import sys, py_compile py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3]) ''' """ Piece of Python code used in :py:func:`waflib.Tools.python.install_pyfile` for installing python files """ DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib'] @extension('.py') def process_py(self, node): """ Add a callback using :py:func:`waflib.Tools.python.install_pyfile` to install a python file """ try: if not self.bld.is_install: return except: return try: if not self.install_path: return except AttributeError: self.install_path = '${PYTHONDIR}' # i wonder now why we wanted to do this after the build is over # issue #901: people want to preserve the structure of installed files def inst_py(ctx): install_from = getattr(self, 'install_from', None) if install_from: install_from = self.path.find_dir(install_from) install_pyfile(self, node, install_from) self.bld.add_post_fun(inst_py) def install_pyfile(self, node, install_from=None): """ Execute the installation of a python file :param node: python file :type node: :py:class:`waflib.Node.Node` """ from_node = install_from or node.parent tsk = self.bld.install_as(self.install_path + '/' + node.path_from(from_node), node, postpone=False) path = tsk.get_install_path() if self.bld.is_install < 0: info("+ removing byte compiled python files") for x in 'co': try: os.remove(path + x) except OSError: pass if self.bld.is_install > 0: try: st1 = os.stat(path) except: error('The python file is missing, this should not happen') for x in ['c', 'o']: do_inst = self.env['PY' + x.upper()] try: st2 = os.stat(path + x) except OSError: pass else: if st1.st_mtime <= st2.st_mtime: do_inst = False if do_inst: lst = (x == 'o') and [self.env['PYFLAGS_OPT']] or [] (a, b, c) = (path, path + x, tsk.get_install_path(destdir=False) + x) argv = self.env['PYTHON'] + lst + ['-c', INST, a, b, c] info('+ byte compiling %r' % (path + x)) env = self.env.env or None ret = Utils.subprocess.Popen(argv, env=env).wait() if ret: raise Errors.WafError('py%s compilation failed %r' % (x, path)) @feature('py') def feature_py(self): """ Dummy feature which does nothing """ pass @feature('pyext') @before_method('propagate_uselib_vars', 'apply_link') @after_method('apply_bundle') def init_pyext(self): """ Change the values of *cshlib_PATTERN* and *cxxshlib_PATTERN* to remove the *lib* prefix from library names. """ try: if not self.install_path: return except AttributeError: self.install_path = '${PYTHONARCHDIR}' self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEXT' in self.uselib: self.uselib.append('PYEXT') # override shlib_PATTERN set by the osx module self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['macbundle_PATTERN'] = self.env['pyext_PATTERN'] @feature('pyext') @before_method('apply_link', 'apply_bundle') def set_bundle(self): if Utils.unversioned_sys_platform() == 'darwin': self.mac_bundle = True @before_method('propagate_uselib_vars') @feature('pyembed') def init_pyembed(self): """ Add the PYEMBED variable. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) if not 'PYEMBED' in self.uselib: self.uselib.append('PYEMBED') @conf def get_python_variables(self, variables, imports=None): """ Spawn a new python process to dump configuration variables :param variables: variables to print :type variables: list of string :param imports: one import by element :type imports: list of string :return: the variable values :rtype: list of string """ if not imports: try: imports = self.python_imports except AttributeError: imports = DISTUTILS_IMP program = list(imports) # copy program.append('') for v in variables: program.append("print(repr(%s))" % v) os_env = dict(os.environ) try: del os_env['MACOSX_DEPLOYMENT_TARGET'] # see comments in the OSX tool except KeyError: pass try: out = self.cmd_and_log(self.env.PYTHON + ['-c', '\n'.join(program)], env=os_env) except Errors.WafError: self.fatal('The distutils module is unusable: install "python-devel"?') return_values = [] for s in out.split('\n'): s = s.strip() if not s: continue if s == 'None': return_values.append(None) elif s[0] == "'" and s[-1] == "'": return_values.append(s[1:-1]) elif s[0].isdigit(): return_values.append(int(s)) else: break return return_values @conf def check_python_headers(conf): """ Check for headers and libraries necessary to extend or embed python by using the module *distutils*. On success the environment variables xxx_PYEXT and xxx_PYEMBED are added: * PYEXT: for compiling python extensions * PYEMBED: for embedding a python interpreter """ # FIXME rewrite if not conf.env['CC_NAME'] and not conf.env['CXX_NAME']: conf.fatal('load a compiler first (gcc, g++, ..)') if not conf.env['PYTHON_VERSION']: conf.check_python_version() env = conf.env pybin = conf.env.PYTHON if not pybin: conf.fatal('could not find the python executable') v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS'.split() try: lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v]) except RuntimeError: conf.fatal("Python development headers not found (-v for details).") vals = ['%s = %r' % (x, y) for (x, y) in zip(v, lst)] conf.to_log("Configuration returned from %r:\n%r\n" % (pybin, '\n'.join(vals))) dct = dict(zip(v, lst)) x = 'MACOSX_DEPLOYMENT_TARGET' if dct[x]: conf.env[x] = conf.environ[x] = dct[x] env['pyext_PATTERN'] = '%s' + dct['SO'] # not a mistake # Check for python libraries for embedding all_flags = dct['LDFLAGS'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEMBED') all_flags = dct['LDFLAGS'] + ' ' + dct['LDSHARED'] + ' ' + dct['CFLAGS'] conf.parse_flags(all_flags, 'PYEXT') result = None #name = 'python' + env['PYTHON_VERSION'] # TODO simplify this for name in ('python' + env['PYTHON_VERSION'], 'python' + env['PYTHON_VERSION'].replace('.', '')): # LIBPATH_PYEMBED is already set; see if it works. if not result and env['LIBPATH_PYEMBED']: path = env['LIBPATH_PYEMBED'] conf.to_log("\n\n# Trying default LIBPATH_PYEMBED: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBPATH_PYEMBED' % name) if not result and dct['LIBDIR']: path = [dct['LIBDIR']] conf.to_log("\n\n# try again with -L$python_LIBDIR: %r\n" % path) result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in LIBDIR' % name) if not result and dct['LIBPL']: path = [dct['LIBPL']] conf.to_log("\n\n# try again with -L$python_LIBPL (some systems don't install the python library in $prefix/lib)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in python_LIBPL' % name) if not result: path = [os.path.join(dct['prefix'], "libs")] conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) if result: break # do not forget to set LIBPATH_PYEMBED if result: env['LIBPATH_PYEMBED'] = path env.append_value('LIB_PYEMBED', [name]) else: conf.to_log("\n\n### LIB NOT FOUND\n") # under certain conditions, python extensions must link to # python libraries, not just python embedding programs. if (Utils.is_win32 or sys.platform.startswith('os2') or dct['Py_ENABLE_SHARED']): env['LIBPATH_PYEXT'] = env['LIBPATH_PYEMBED'] env['LIB_PYEXT'] = env['LIB_PYEMBED'] # We check that pythonX.Y-config exists, and if it exists we # use it to get only the includes, else fall back to distutils. num = '.'.join(env['PYTHON_VERSION'].split('.')[:2]) conf.find_program(['python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', mandatory=False) includes = [] if conf.env.PYTHON_CONFIG: for incstr in conf.cmd_and_log([ conf.env.PYTHON_CONFIG, '--includes']).strip().split(): # strip the -I or /I if (incstr.startswith('-I') or incstr.startswith('/I')): incstr = incstr[2:] # append include path, unless already given if incstr not in includes: includes.append(incstr) conf.to_log("Include path for Python extensions (found via python-config --includes): %r\n" % (includes,)) env['INCLUDES_PYEXT'] = includes env['INCLUDES_PYEMBED'] = includes else: conf.to_log("Include path for Python extensions " "(found via distutils module): %r\n" % (dct['INCLUDEPY'],)) env['INCLUDES_PYEXT'] = [dct['INCLUDEPY']] env['INCLUDES_PYEMBED'] = [dct['INCLUDEPY']] # Code using the Python API needs to be compiled with -fno-strict-aliasing if env['CC_NAME'] == 'gcc': env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing']) if env['CXX_NAME'] == 'gcc': env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CC_NAME == "msvc": from distutils.msvccompiler import MSVCCompiler dist_compiler = MSVCCompiler() dist_compiler.initialize() env.append_value('CFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('CXXFLAGS_PYEXT', dist_compiler.compile_options) env.append_value('LINKFLAGS_PYEXT', dist_compiler.ldflags_shared) # See if it compiles try: conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', uselib='PYEMBED', fragment=FRAG, errmsg='Could not find the python development headers') except conf.errors.ConfigurationError: # python3.2, oh yeah conf.check_cfg(path=conf.env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=['--cflags', '--libs']) conf.check(header_name='Python.h', define_name='HAVE_PYTHON_H', msg='Getting the python flags from python-config', uselib='PYEMBED', fragment=FRAG, errmsg='Could not find the python development headers elsewhere') @conf def check_python_version(conf, minver=None): """ Check if the python interpreter is found matching a given minimum version. minver should be a tuple, eg. to check for python >= 2.4.2 pass (2,4,2) as minver. If successful, PYTHON_VERSION is defined as 'MAJOR.MINOR' (eg. '2.4') of the actual python version found, and PYTHONDIR is defined, pointing to the site-packages directory appropriate for this python version, where modules/packages/extensions should be installed. :param minver: minimum version :type minver: tuple of int """ assert minver is None or isinstance(minver, tuple) pybin = conf.env['PYTHON'] if not pybin: conf.fatal('could not find the python executable') # Get python version string cmd = pybin + ['-c', 'import sys\nfor x in sys.version_info: print(str(x))'] debug('python: Running python command %r' % cmd) lines = conf.cmd_and_log(cmd).split() assert len(lines) == 5, "found %i lines, expected 5: %r" % (len(lines), lines) pyver_tuple = (int(lines[0]), int(lines[1]), int(lines[2]), lines[3], int(lines[4])) # compare python version with the minimum required result = (minver is None) or (pyver_tuple >= minver) if result: # define useful environment variables pyver = '.'.join([str(x) for x in pyver_tuple[:2]]) conf.env['PYTHON_VERSION'] = pyver if 'PYTHONDIR' in conf.environ: pydir = conf.environ['PYTHONDIR'] else: if Utils.is_win32: (python_LIBDEST, pydir) = conf.get_python_variables( ["get_config_var('LIBDEST') or ''", "get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) else: python_LIBDEST = None (pydir,) = conf.get_python_variables( ["get_python_lib(standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) if python_LIBDEST is None: if conf.env['LIBDIR']: python_LIBDEST = os.path.join(conf.env['LIBDIR'], "python" + pyver) else: python_LIBDEST = os.path.join(conf.env['PREFIX'], "lib", "python" + pyver) if 'PYTHONARCHDIR' in conf.environ: pyarchdir = conf.environ['PYTHONARCHDIR'] else: (pyarchdir, ) = conf.get_python_variables( ["get_python_lib(plat_specific=1, standard_lib=0, prefix=%r) or ''" % conf.env['PREFIX']]) if not pyarchdir: pyarchdir = pydir if hasattr(conf, 'define'): # conf.define is added by the C tool, so may not exist conf.define('PYTHONDIR', pydir) conf.define('PYTHONARCHDIR', pyarchdir) conf.env['PYTHONDIR'] = pydir conf.env['PYTHONARCHDIR'] = pyarchdir # Feedback pyver_full = '.'.join(map(str, pyver_tuple[:3])) if minver is None: conf.msg('Checking for python version', pyver_full) else: minver_str = '.'.join(map(str, minver)) conf.msg('Checking for python version', pyver_tuple, ">= %s" % (minver_str,) and 'GREEN' or 'YELLOW') if not result: conf.fatal('The python version is too old, expecting %r' % (minver,)) PYTHON_MODULE_TEMPLATE = ''' import %s as current_module version = getattr(current_module, '__version__', None) if version is not None: print(str(version)) else: print('unknown version') ''' @conf def check_python_module(conf, module_name, condition=''): """ Check if the selected python interpreter can import the given python module:: def configure(conf): conf.check_python_module('pygccxml') conf.check_python_module('re', condition="ver > num(2, 0, 4) and ver <= num(3, 0, 0)") :param module_name: module :type module_name: string """ msg = 'Python module %s' % module_name if condition: msg = '%s (%s)' % (msg, condition) conf.start_msg(msg) try: ret = conf.cmd_and_log(conf.env['PYTHON'] + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) except Exception: conf.end_msg(False) conf.fatal('Could not find the python module %r' % module_name) ret = ret.strip() if condition: conf.end_msg(ret) if ret == 'unknown version': conf.fatal('Could not check the %s version' % module_name) from distutils.version import LooseVersion def num(*k): if isinstance(k[0], int): return LooseVersion('.'.join([str(x) for x in k])) else: return LooseVersion(k[0]) d = {'num': num, 'ver': LooseVersion(ret)} ev = eval(condition, {}, d) if not ev: conf.fatal('The %s version does not satisfy the requirements' % module_name) else: if ret == 'unknown version': conf.end_msg(True) else: conf.end_msg(ret) def configure(conf): """ Detect the python interpreter """ try: conf.find_program('python', var='PYTHON') except conf.errors.ConfigurationError: warn("could not find a python executable, setting to sys.executable '%s'" % sys.executable) conf.env.PYTHON = sys.executable if conf.env.PYTHON != sys.executable: warn("python executable '%s' different from sys.executable '%s'" % (conf.env.PYTHON, sys.executable)) conf.env.PYTHON = conf.cmd_to_list(conf.env.PYTHON) v = conf.env v['PYCMD'] = '"import sys, py_compile;py_compile.compile(sys.argv[1], sys.argv[2])"' v['PYFLAGS'] = '' v['PYFLAGS_OPT'] = '-O' v['PYC'] = getattr(Options.options, 'pyc', 1) v['PYO'] = getattr(Options.options, 'pyo', 1) def options(opt): """ Add the options ``--nopyc`` and ``--nopyo`` """ opt.add_option('--nopyc', action='store_false', default=1, help = 'Do not install bytecode compiled .pyc files (configuration) [Default:install]', dest = 'pyc') opt.add_option('--nopyo', action='store_false', default=1, help='Do not install optimised compiled .pyo files (configuration) [Default:install]', dest='pyo') debian/waf-1.6/waflib/Tools/c.py0000664000000000000000000000274712145744415013430 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) "Base for c programs/libraries" from waflib import TaskGen, Task, Utils from waflib.Tools import c_preproc from waflib.Tools.ccroot import link_task, stlink_task @TaskGen.extension('.c') def c_hook(self, node): "Bind the c file extension to the creation of a :py:class:`waflib.Tools.c.c` instance" return self.create_compiled_task('c', node) class c(Task.Task): "Compile C files into object files" run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT}' vars = ['CCDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan Task.classes['cc'] = cc = c # compat, remove in waf 1.7 class cprogram(link_task): "Link object files into a c program" run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' ext_out = ['.bin'] vars = ['LINKDEPS'] inst_to = '${BINDIR}' chmod = Utils.O755 class cshlib(cprogram): "Link object files into a c shared library" inst_to = '${LIBDIR}' class cstlib(stlink_task): "Link object files into a c static library" pass # do not remove debian/waf-1.6/waflib/Tools/gnu_dirs.py0000664000000000000000000001207512145744415015013 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ Sets various standard variables such as INCLUDEDIR. SBINDIR and others. To use this module just call:: opt.load('gnu_dirs') and:: conf.load('gnu_dirs') Add options for the standard GNU directories, this tool will add the options found in autotools, and will update the environment with the following installation variables: ============== ========================================= ======================= Variable Description Value ============== ========================================= ======================= PREFIX architecture-independent files /usr/local EXEC_PREFIX architecture-dependent files PREFIX BINDIR user executables EXEC_PREFIX/bin SBINDIR user executables EXEC_PREFIX/sbin LIBEXECDIR program executables EXEC_PREFIX/libexec SYSCONFDIR read-only single-machine data PREFIX/etc SHAREDSTATEDIR modifiable architecture-independent data PREFIX/com LOCALSTATEDIR modifiable single-machine data PREFIX/var LIBDIR object code libraries EXEC_PREFIX/lib INCLUDEDIR C header files PREFIX/include OLDINCLUDEDIR C header files for non-gcc /usr/include DATAROOTDIR read-only arch.-independent data root PREFIX/share DATADIR read-only architecture-independent data DATAROOTDIR INFODIR info documentation DATAROOTDIR/info LOCALEDIR locale-dependent data DATAROOTDIR/locale MANDIR man documentation DATAROOTDIR/man DOCDIR documentation root DATAROOTDIR/doc/APPNAME HTMLDIR html documentation DOCDIR DVIDIR dvi documentation DOCDIR PDFDIR pdf documentation DOCDIR PSDIR ps documentation DOCDIR ============== ========================================= ======================= """ import os from waflib import Utils, Options, Context _options = [x.split(', ') for x in ''' bindir, user executables, ${EXEC_PREFIX}/bin sbindir, system admin executables, ${EXEC_PREFIX}/sbin libexecdir, program executables, ${EXEC_PREFIX}/libexec sysconfdir, read-only single-machine data, ${PREFIX}/etc sharedstatedir, modifiable architecture-independent data, ${PREFIX}/com localstatedir, modifiable single-machine data, ${PREFIX}/var libdir, object code libraries, ${EXEC_PREFIX}/lib includedir, C header files, ${PREFIX}/include oldincludedir, C header files for non-gcc, /usr/include datarootdir, read-only arch.-independent data root, ${PREFIX}/share datadir, read-only architecture-independent data, ${DATAROOTDIR} infodir, info documentation, ${DATAROOTDIR}/info localedir, locale-dependent data, ${DATAROOTDIR}/locale mandir, man documentation, ${DATAROOTDIR}/man docdir, documentation root, ${DATAROOTDIR}/doc/${PACKAGE} htmldir, html documentation, ${DOCDIR} dvidir, dvi documentation, ${DOCDIR} pdfdir, pdf documentation, ${DOCDIR} psdir, ps documentation, ${DOCDIR} '''.split('\n') if x] def configure(conf): """ Read the command-line options to set lots of variables in *conf.env*. The variables BINDIR and LIBDIR will be overwritten. """ def get_param(varname, default): return getattr(Options.options, varname, '') or default env = conf.env conf.env.LIBDIR = conf.env.BINDIR = [] env['EXEC_PREFIX'] = get_param('EXEC_PREFIX', env['PREFIX']) env['PACKAGE'] = getattr(Context.g_module, 'APPNAME', None) or env['PACKAGE'] complete = False iter = 0 while not complete and iter < len(_options) + 1: iter += 1 complete = True for name, help, default in _options: name = name.upper() if not env[name]: try: env[name] = Utils.subst_vars(get_param(name, default).replace('/', os.sep), env) except TypeError: complete = False if not complete: lst = [name for name, _, _ in _options if not env[name.upper()]] raise conf.errors.WafError('Variable substitution failure %r' % lst) def options(opt): """ Add lots of command-line options, for example:: --exec-prefix: EXEC_PREFIX """ inst_dir = opt.add_option_group('Installation directories', 'By default, "waf install" will put the files in\ "/usr/local/bin", "/usr/local/lib" etc. An installation prefix other\ than "/usr/local" can be given using "--prefix", for example "--prefix=$HOME"') for k in ('--prefix', '--destdir'): option = opt.parser.get_option(k) if option: opt.parser.remove_option(k) inst_dir.add_option(option) inst_dir.add_option('--exec-prefix', help = 'installation prefix [Default: ${PREFIX}]', default = '', dest = 'EXEC_PREFIX') dirs_options = opt.add_option_group('Pre-defined installation directories', '') for name, help, default in _options: option_name = '--' + name str_default = default str_help = '%s [Default: %s]' % (help, str_default) dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) debian/waf-1.6/waflib/Tools/waf_unit_test.py0000664000000000000000000001041212145744415016045 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 # Thomas Nagy, 2010 """ Unit testing system for C/C++/D providing test execution: * in parallel, by using ``waf -j`` * partial (only the tests that have changed) or full (by using ``waf --alltests``) The tests are declared by adding the **test** feature to programs:: def options(opt): opt.load('compiler_cxx waf_unit_test') def configure(conf): conf.load('compiler_cxx waf_unit_test') def build(bld): bld(features='cxx cxxprogram test', source='main.cpp', target='app') # or bld.program(features='test', source='main2.cpp', target='app2') When the build is executed, the program 'test' will be built and executed without arguments. The success/failure is detected by looking at the return code. The status and the standard output/error are stored on the build context. The results can be displayed by registering a callback function. Here is how to call the predefined callback:: def build(bld): bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.summary) """ import os, sys from waflib.TaskGen import feature, after_method from waflib import Utils, Task, Logs, Options testlock = Utils.threading.Lock() @feature('test') @after_method('apply_link') def make_test(self): """Create the unit test task. There can be only one unit test task by task generator.""" if getattr(self, 'link_task', None): self.create_task('utest', self.link_task.outputs) class utest(Task.Task): """ Execute a unit test """ color = 'PINK' after = ['vnum', 'inst'] vars = [] def runnable_status(self): """ Always execute the task if `waf --alltests` was used """ ret = super(utest, self).runnable_status() if ret == Task.SKIP_ME: if getattr(Options.options, 'all_tests', False): return Task.RUN_ME return ret def run(self): """ Execute the test. The execution is always successful, but the results are stored on ``self.generator.bld.utest_results`` for postprocessing. """ filename = self.inputs[0].abspath() self.ut_exec = getattr(self, 'ut_exec', [filename]) if getattr(self.generator, 'ut_fun', None): self.generator.ut_fun(self) try: fu = getattr(self.generator.bld, 'all_test_paths') except AttributeError: fu = os.environ.copy() self.generator.bld.all_test_paths = fu lst = [] for g in self.generator.bld.groups: for tg in g: if getattr(tg, 'link_task', None): lst.append(tg.link_task.outputs[0].parent.abspath()) def add_path(dct, path, var): dct[var] = os.pathsep.join(Utils.to_list(path) + [os.environ.get(var, '')]) if Utils.is_win32: add_path(fu, lst, 'PATH') elif Utils.unversioned_sys_platform() == 'darwin': add_path(fu, lst, 'DYLD_LIBRARY_PATH') add_path(fu, lst, 'LD_LIBRARY_PATH') else: add_path(fu, lst, 'LD_LIBRARY_PATH') cwd = getattr(self.generator, 'ut_cwd', '') or self.inputs[0].parent.abspath() proc = Utils.subprocess.Popen(self.ut_exec, cwd=cwd, env=fu, stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE) (stdout, stderr) = proc.communicate() tup = (filename, proc.returncode, stdout, stderr) self.generator.utest_result = tup testlock.acquire() try: bld = self.generator.bld Logs.debug("ut: %r", tup) try: bld.utest_results.append(tup) except AttributeError: bld.utest_results = [tup] finally: testlock.release() def summary(bld): """ Display an execution summary:: def build(bld): bld(features='cxx cxxprogram test', source='main.c', target='app') from waflib.Tools import waf_unit_test bld.add_post_fun(waf_unit_test.summary) """ lst = getattr(bld, 'utest_results', []) if lst: Logs.pprint('CYAN', 'execution summary') total = len(lst) tfail = len([x for x in lst if x[1]]) Logs.pprint('CYAN', ' tests that pass %d/%d' % (total-tfail, total)) for (f, code, out, err) in lst: if not code: Logs.pprint('CYAN', ' %s' % f) Logs.pprint('CYAN', ' tests that fail %d/%d' % (tfail, total)) for (f, code, out, err) in lst: if code: Logs.pprint('CYAN', ' %s' % f) def options(opt): """ Provide the ``--alltests`` command-line option. """ opt.add_option('--alltests', action='store_true', default=False, help='Exec all unit tests', dest='all_tests') debian/waf-1.6/waflib/Tools/fc.py0000664000000000000000000001474412145744415013576 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) """ fortran support """ import re from waflib import Utils, Task, TaskGen, Logs from waflib.Tools import ccroot, fc_config, fc_scan from waflib.TaskGen import feature, before_method, after_method, extension from waflib.Configure import conf ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES']) ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) @feature('fcprogram', 'fcshlib', 'fcstlib', 'fcprogram_test') def dummy(self): pass @extension('.f', '.f90', '.F', '.F90', '.for', '.FOR') def fc_hook(self, node): "Bind the typical Fortran file extensions to the creation of a :py:class:`waflib.Tools.fc.fc` instance" return self.create_compiled_task('fc', node) @conf def modfile(conf, name): """ Turn a module name into the right module file name. Defaults to all lower case. """ return {'lower' :name.lower() + '.mod', 'lower.MOD' :name.upper() + '.MOD', 'UPPER.mod' :name.upper() + '.mod', 'UPPER' :name.upper() + '.MOD'}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] def get_fortran_tasks(tsk): """ Obtain all other fortran tasks from the same build group. Those tasks must not have the attribute 'nomod' or 'mod_fortran_done' """ bld = tsk.generator.bld tasks = bld.get_tasks_group(bld.get_group_idx(tsk.generator)) return [x for x in tasks if isinstance(x, fc) and not getattr(x, 'nomod', None) and not getattr(x, 'mod_fortran_done', None)] class fc(Task.Task): """ The fortran tasks can only run when all fortran tasks in the current group are ready to be executed This may cause a deadlock if another fortran task is waiting for something that cannot happen (circular dependency) in this case, set the 'nomod=True' on those tasks instances to break the loop """ color = 'GREEN' run_str = '${FC} ${FCFLAGS} ${FCINCPATH_ST:INCPATHS} ${FCDEFINES_ST:DEFINES} ${_FCMODOUTFLAGS} ${FC_TGT_F}${TGT[0].abspath()} ${FC_SRC_F}${SRC[0].abspath()}' vars = ["FORTRANMODPATHFLAG"] def scan(self): """scanner for fortran dependencies""" tmp = fc_scan.fortran_parser(self.generator.includes_nodes) tmp.task = self tmp.start(self.inputs[0]) if Logs.verbose: Logs.debug('deps: deps for %r: %r; unresolved %r' % (self.inputs, tmp.nodes, tmp.names)) return (tmp.nodes, tmp.names) def runnable_status(self): """ Set the mod file outputs and the dependencies on the mod files over all the fortran tasks executed by the main thread so there are no concurrency issues """ if getattr(self, 'mod_fortran_done', None): return super(fc, self).runnable_status() # now, if we reach this part it is because this fortran task is the first in the list bld = self.generator.bld # obtain the fortran tasks lst = get_fortran_tasks(self) # disable this method for other tasks for tsk in lst: tsk.mod_fortran_done = True # wait for all the .f tasks to be ready for execution # and ensure that the scanners are called at least once for tsk in lst: ret = tsk.runnable_status() if ret == Task.ASK_LATER: # we have to wait for one of the other fortran tasks to be ready # this may deadlock if there are dependencies between the fortran tasks # but this should not happen (we are setting them here!) for x in lst: x.mod_fortran_done = None # TODO sort the list of tasks in bld.producer.outstanding to put all fortran tasks at the end return Task.ASK_LATER ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) # the .mod files to create for tsk in lst: key = tsk.uid() for x in bld.raw_deps[key]: if x.startswith('MOD@'): name = bld.modfile(x.replace('MOD@', '')) node = bld.srcnode.find_or_declare(name) tsk.set_outputs(node) outs[id(node)].add(tsk) # the .mod files to use for tsk in lst: key = tsk.uid() for x in bld.raw_deps[key]: if x.startswith('USE@'): name = bld.modfile(x.replace('USE@', '')) node = bld.srcnode.find_resource(name) if node and node not in tsk.outputs: if not node in bld.node_deps[key]: bld.node_deps[key].append(node) ins[id(node)].add(tsk) # if the intersection matches, set the order for k in ins.keys(): for a in ins[k]: a.run_after.update(outs[k]) # the scanner cannot output nodes, so we have to set them # ourselves as task.dep_nodes (additional input nodes) tmp = [] for t in outs[k]: tmp.extend(t.outputs) a.dep_nodes.extend(tmp) # old python versions try: a.dep_nodes.sort(key=lambda x: x.abspath()) except: a.dep_nodes.sort(lambda x, y: cmp(x.abspath(), y.abspath())) # the task objects have changed: clear the signature cache for tsk in lst: try: delattr(tsk, 'cache_sig') except AttributeError: pass return super(fc, self).runnable_status() class fcprogram(ccroot.link_task): """Link fortran programs""" color = 'YELLOW' run_str = '${FC} ${LINKFLAGS} ${FCLNK_SRC_F}${SRC} ${FCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FCSTLIB_MARKER} ${FCSTLIBPATH_ST:STLIBPATH} ${FCSTLIB_ST:STLIB} ${FCSHLIB_MARKER} ${FCLIBPATH_ST:LIBPATH} ${FCLIB_ST:LIB}' inst_to = '${BINDIR}' chmod = Utils.O755 class fcshlib(fcprogram): """Link fortran libraries""" inst_to = '${LIBDIR}' class fcprogram_test(fcprogram): """Custom link task to obtain the compiler outputs for fortran configuration tests""" def can_retrieve_cache(self): """This task is always executed""" return False def runnable_status(self): """This task is always executed""" ret = super(fcprogram_test, self).runnable_status() if ret == Task.SKIP_ME: ret = Task.RUN_ME return ret def exec_command(self, cmd, **kw): """Store the compiler std our/err onto the build context, to bld.out + bld.err""" bld = self.generator.bld kw['shell'] = isinstance(cmd, str) kw['stdout'] = kw['stderr'] = Utils.subprocess.PIPE kw['cwd'] = bld.variant_dir bld.out = bld.err = '' bld.to_log('command: %s\n' % cmd) kw['output'] = 0 try: (bld.out, bld.err) = bld.cmd_and_log(cmd, **kw) except Exception as e: return -1 if bld.out: bld.to_log("out: %s\n" % bld.out) if bld.err: bld.to_log("err: %s\n" % bld.err) class fcstlib(ccroot.stlink_task): """Link fortran static libraries (uses ar by default)""" pass # do not remove the pass statement debian/waf-1.6/waflib/Tools/nasm.py0000664000000000000000000000102012145744415014123 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Nasm tool (asm processing) """ import waflib.Tools.asm # leave this from waflib.TaskGen import feature @feature('asm') def apply_nasm_vars(self): """provided for compatibility""" self.env.append_value('ASFLAGS', self.to_list(getattr(self, 'nasm_flags', []))) def configure(conf): """ Detect nasm/yasm and set the variable *AS* """ nasm = conf.find_program(['nasm', 'yasm'], var='AS') conf.env.AS_TGT_F = ['-o'] conf.env.ASLNK_TGT_F = ['-o'] debian/waf-1.6/waflib/Tools/cxx.py0000664000000000000000000000321712145744415014001 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "Base for c++ programs and libraries" from waflib import TaskGen, Task, Utils from waflib.Tools import c_preproc from waflib.Tools.ccroot import link_task, stlink_task def cxx_hook(self, node): "Bind the c++ file extensions to the creation of a :py:class:`waflib.Tools.cxx.cxx` instance" return self.create_compiled_task('cxx', node) TaskGen.extension('.cpp','.cc','.cxx','.C','.c++')(cxx_hook) # leave like this for python 2.3 if not '.c' in TaskGen.task_gen.mappings: TaskGen.task_gen.mappings['.c'] = TaskGen.task_gen.mappings['.cpp'] class cxx(Task.Task): "Compile C++ files into object files" run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT}' vars = ['CXXDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan class cxxprogram(link_task): "Link object files into a c++ program" run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB}' vars = ['LINKDEPS'] ext_out = ['.bin'] inst_to = '${BINDIR}' chmod = Utils.O755 class cxxshlib(cxxprogram): "Link object files into a c++ shared library" inst_to = '${LIBDIR}' class cxxstlib(stlink_task): "Link object files into a c++ static library" pass # do not remove debian/waf-1.6/waflib/Tools/fc_config.py0000664000000000000000000003221712145744415015116 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) """ Fortran configuration helpers """ import re, shutil, os, sys, string, shlex from waflib.Configure import conf from waflib.TaskGen import feature, after_method, before_method from waflib import Build, Utils FC_FRAGMENT = ' program main\n end program main\n' FC_FRAGMENT2 = ' PROGRAM MAIN\n END\n' # what's the actual difference between these? @conf def fc_flags(conf): """ Define common fortran configuration flags and file extensions """ v = conf.env v['FC_SRC_F'] = [] v['FC_TGT_F'] = ['-c', '-o'] v['FCINCPATH_ST'] = '-I%s' v['FCDEFINES_ST'] = '-D%s' if not v['LINK_FC']: v['LINK_FC'] = v['FC'] v['FCLNK_SRC_F'] = [] v['FCLNK_TGT_F'] = ['-o'] v['FCFLAGS_fcshlib'] = ['-fpic'] v['LINKFLAGS_fcshlib'] = ['-shared'] v['fcshlib_PATTERN'] = 'lib%s.so' v['fcstlib_PATTERN'] = 'lib%s.a' v['FCLIB_ST'] = '-l%s' v['FCLIBPATH_ST'] = '-L%s' v['FCSTLIB_ST'] = '-l%s' v['FCSTLIBPATH_ST'] = '-L%s' v['FCSTLIB_MARKER'] = '-Wl,-Bstatic' v['FCSHLIB_MARKER'] = '-Wl,-Bdynamic' v['SONAME_ST'] = '-Wl,-h,%s' @conf def check_fortran(self, *k, **kw): """See if the fortran compiler works by compiling a simple fortran program""" self.check_cc( fragment = FC_FRAGMENT, compile_filename = 'test.f', features = 'fc fcprogram', msg = 'Compiling a simple fortran app') @conf def check_fc(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *Fortran* programming language (Overriding the C defaults in :py:func:`waflib.Tools.c_config.validate_c` here) """ kw['compiler'] = 'fc' if not 'compile_mode' in kw: kw['compile_mode'] = 'fc' if not 'type' in kw: kw['type'] = 'fcprogram' if not 'compile_filename' in kw: kw['compile_filename'] = 'test.f90' if not 'code' in kw: kw['code'] = FC_FRAGMENT return self.check(*k, **kw) # ------------------------------------------------------------------------ # --- These are the default platform modifiers, refactored here for # convenience. gfortran and g95 have much overlap. # ------------------------------------------------------------------------ @conf def fortran_modifier_darwin(conf): """ Define fortran flags and extensions for the OSX systems """ v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC', '-compatibility_version', '1', '-current_version', '1'] v['LINKFLAGS_fcshlib'] = ['-dynamiclib'] v['fcshlib_PATTERN'] = 'lib%s.dylib' v['FRAMEWORKPATH_ST'] = '-F%s' v['FRAMEWORK_ST'] = '-framework %s' v['LINKFLAGS_fcstlib'] = [] v['FCSHLIB_MARKER'] = '' v['FCSTLIB_MARKER'] = '' v['SONAME_ST'] = '' @conf def fortran_modifier_win32(conf): """Define fortran flags for the windows platforms""" v = conf.env v['fcprogram_PATTERN'] = v['fcprogram_test_PATTERN'] = '%s.exe' v['fcshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = 'lib%s.dll.a' v['IMPLIB_ST'] = '-Wl,--out-implib,%s' v['FCFLAGS_fcshlib'] = [] v.append_value('FCFLAGS_fcshlib', ['-DDLL_EXPORT']) # TODO adding nonstandard defines like this DLL_EXPORT is not a good idea # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def fortran_modifier_cygwin(conf): """Define fortran flags for use on cygwin""" fortran_modifier_win32(conf) v = conf.env v['fcshlib_PATTERN'] = 'cyg%s.dll' v.append_value('LINKFLAGS_fcshlib', ['-Wl,--enable-auto-image-base']) v['FCFLAGS_fcshlib'] = [] # ------------------------------------------------------------------------ @conf def check_fortran_dummy_main(self, *k, **kw): """ Guess if a main function is needed by compiling a code snippet with the C compiler and link with the Fortran compiler TODO: (DC) - handling dialects (F77, F90, etc... -> needs core support first) - fix dummy main check (AC_FC_DUMMY_MAIN vs AC_FC_MAIN) TODO: what does the above mean? (ita) """ if not self.env.CC: self.fatal('A c compiler is required for check_fortran_dummy_main') lst = ['MAIN__', '__MAIN', '_MAIN', 'MAIN_', 'MAIN'] lst.extend([m.lower() for m in lst]) lst.append('') self.start_msg('Detecting whether we need a dummy main') for main in lst: kw['fortran_main'] = main try: self.check_cc( fragment = 'int %s() { return 0; }\n' % (main or 'test'), features = 'c fcprogram', mandatory = True ) if not main: self.env.FC_MAIN = -1 self.end_msg('no') else: self.env.FC_MAIN = main self.end_msg('yes %s' % main) break except self.errors.ConfigurationError: pass else: self.end_msg('not found') self.fatal('could not detect whether fortran requires a dummy main, see the config.log') # ------------------------------------------------------------------------ GCC_DRIVER_LINE = re.compile('^Driving:') POSIX_STATIC_EXT = re.compile('\S+\.a') POSIX_LIB_FLAGS = re.compile('-l\S+') @conf def is_link_verbose(self, txt): """Return True if 'useful' link options can be found in txt""" assert isinstance(txt, str) for line in txt.splitlines(): if not GCC_DRIVER_LINE.search(line): if POSIX_STATIC_EXT.search(line) or POSIX_LIB_FLAGS.search(line): return True return False @conf def check_fortran_verbose_flag(self, *k, **kw): """ Check what kind of verbose (-v) flag works, then set it to env.FC_VERBOSE_FLAG """ self.start_msg('fortran link verbose flag') for x in ['-v', '--verbose', '-verbose', '-V']: try: self.check_cc( features = 'fc fcprogram_test', fragment = FC_FRAGMENT2, compile_filename = 'test.f', linkflags = [x], mandatory=True ) except self.errors.ConfigurationError: pass else: # output is on stderr or stdout (for xlf) if self.is_link_verbose(self.test_bld.err) or self.is_link_verbose(self.test_bld.out): self.end_msg(x) break else: self.end_msg('failure') self.fatal('Could not obtain the fortran link verbose flag (see config.log)') self.env.FC_VERBOSE_FLAG = x return x # ------------------------------------------------------------------------ # linkflags which match those are ignored LINKFLAGS_IGNORED = [r'-lang*', r'-lcrt[a-zA-Z0-9\.]*\.o', r'-lc$', r'-lSystem', r'-libmil', r'-LIST:*', r'-LNO:*'] if os.name == 'nt': LINKFLAGS_IGNORED.extend([r'-lfrt*', r'-luser32', r'-lkernel32', r'-ladvapi32', r'-lmsvcrt', r'-lshell32', r'-lmingw', r'-lmoldname']) else: LINKFLAGS_IGNORED.append(r'-lgcc*') RLINKFLAGS_IGNORED = [re.compile(f) for f in LINKFLAGS_IGNORED] def _match_ignore(line): """Returns True if the line should be ignored (fortran test for verbosity).""" for i in RLINKFLAGS_IGNORED: if i.match(line): return True return False def parse_fortran_link(lines): """Given the output of verbose link of Fortran compiler, this returns a list of flags necessary for linking using the standard linker.""" # TODO: On windows ? final_flags = [] for line in lines: if not GCC_DRIVER_LINE.match(line): _parse_flink_line(line, final_flags) return final_flags SPACE_OPTS = re.compile('^-[LRuYz]$') NOSPACE_OPTS = re.compile('^-[RL]') def _parse_flink_line(line, final_flags): """private""" lexer = shlex.shlex(line, posix = True) lexer.whitespace_split = True t = lexer.get_token() tmp_flags = [] while t: def parse(token): # Here we go (convention for wildcard is shell, not regex !) # 1 TODO: we first get some root .a libraries # 2 TODO: take everything starting by -bI:* # 3 Ignore the following flags: -lang* | -lcrt*.o | -lc | # -lgcc* | -lSystem | -libmil | -LANG:=* | -LIST:* | -LNO:*) # 4 take into account -lkernel32 # 5 For options of the kind -[[LRuYz]], as they take one argument # after, the actual option is the next token # 6 For -YP,*: take and replace by -Larg where arg is the old # argument # 7 For -[lLR]*: take # step 3 if _match_ignore(token): pass # step 4 elif token.startswith('-lkernel32') and sys.platform == 'cygwin': tmp_flags.append(token) # step 5 elif SPACE_OPTS.match(token): t = lexer.get_token() if t.startswith('P,'): t = t[2:] for opt in t.split(os.pathsep): tmp_flags.append('-L%s' % opt) # step 6 elif NOSPACE_OPTS.match(token): tmp_flags.append(token) # step 7 elif POSIX_LIB_FLAGS.match(token): tmp_flags.append(token) else: # ignore anything not explicitely taken into account pass t = lexer.get_token() return t t = parse(t) final_flags.extend(tmp_flags) return final_flags @conf def check_fortran_clib(self, autoadd=True, *k, **kw): """ Obtain the flags for linking with the C library if this check works, add uselib='CLIB' to your task generators """ if not self.env.FC_VERBOSE_FLAG: self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') self.start_msg('Getting fortran runtime link flags') try: self.check_cc( fragment = FC_FRAGMENT2, compile_filename = 'test.f', features = 'fc fcprogram_test', linkflags = [self.env.FC_VERBOSE_FLAG] ) except: self.end_msg(False) if kw.get('mandatory', True): conf.fatal('Could not find the c library flags') else: out = self.test_bld.err flags = parse_fortran_link(out.splitlines()) self.end_msg('ok (%s)' % ' '.join(flags)) self.env.LINKFLAGS_CLIB = flags return flags return [] def getoutput(conf, cmd, stdin=False): """ TODO a bit redundant, can be removed anytime """ if stdin: stdin = Utils.subprocess.PIPE else: stdin = None env = conf.env.env or None try: p = Utils.subprocess.Popen(cmd, stdin=stdin, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env) if stdin: p.stdin.write('\n'.encode()) stdout, stderr = p.communicate() except: conf.fatal('could not determine the compiler version %r' % cmd) else: if not isinstance(stdout, str): stdout = stdout.decode(sys.stdout.encoding) if not isinstance(stderr, str): stderr = stderr.decode(sys.stdout.encoding) return stdout, stderr # ------------------------------------------------------------------------ ROUTINES_CODE = """\ subroutine foobar() return end subroutine foo_bar() return end """ MAIN_CODE = """ void %(dummy_func_nounder)s(void); void %(dummy_func_under)s(void); int %(main_func_name)s() { %(dummy_func_nounder)s(); %(dummy_func_under)s(); return 0; } """ @feature('link_main_routines_func') @before_method('process_source') def link_main_routines_tg_method(self): """ The configuration test declares a unique task generator, so we create other task generators from there for fortran link tests """ def write_test_file(task): task.outputs[0].write(task.generator.code) bld = self.bld bld(rule=write_test_file, target='main.c', code=MAIN_CODE % self.__dict__) bld(rule=write_test_file, target='test.f', code=ROUTINES_CODE) bld(features='fc fcstlib', source='test.f', target='test') bld(features='c fcprogram', source='main.c', target='app', use='test') def mangling_schemes(): """ Generate triplets for use with mangle_name (used in check_fortran_mangling) the order is tuned for gfortan """ for u in ['_', '']: for du in ['', '_']: for c in ["lower", "upper"]: yield (u, du, c) def mangle_name(u, du, c, name): """Mangle a name from a triplet (used in check_fortran_mangling)""" return getattr(name, c)() + u + (name.find('_') != -1 and du or '') @conf def check_fortran_mangling(self, *k, **kw): """ Detect the mangling scheme, sets FORTRAN_MANGLING to the triplet found This test will compile a fortran static library, then link a c app against it """ if not self.env.CC: self.fatal('A c compiler is required for link_main_routines') if not self.env.FC: self.fatal('A fortran compiler is required for link_main_routines') if not self.env.FC_MAIN: self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') self.start_msg('Getting fortran mangling scheme') for (u, du, c) in mangling_schemes(): try: self.check_cc( compile_filename = [], features = 'link_main_routines_func', msg = 'nomsg', errmsg = 'nomsg', mandatory=True, dummy_func_nounder = mangle_name(u, du, c, "foobar"), dummy_func_under = mangle_name(u, du, c, "foo_bar"), main_func_name = self.env.FC_MAIN ) except self.errors.ConfigurationError: pass else: self.end_msg("ok ('%s', '%s', '%s-case')" % (u, du, c)) self.env.FORTRAN_MANGLING = (u, du, c) break else: self.end_msg(False) self.fatal('mangler not found') return (u, du, c) @feature('pyext') @before_method('propagate_uselib_vars', 'apply_link') def set_lib_pat(self): """Set the fortran flags for linking with the python library""" self.env['fcshlib_PATTERN'] = self.env['pyext_PATTERN'] @conf def detect_openmp(self): for x in ['-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp']: try: self.check_fc( msg='Checking for OpenMP flag %s' % x, fragment='program main\n call omp_get_num_threads()\nend program main', fcflags=x, linkflags=x, uselib_store='OPENMP' ) except self.errors.ConfigurationError: pass else: break else: self.fatal('Could not find OpenMP') debian/waf-1.6/waflib/Tools/cs.py0000664000000000000000000001243312145744415013604 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ C# support. A simple example:: def configure(conf): conf.load('cs') def build(bld): bld(features='cs', source='main.cs', gen='foo') Note that the configuration may compile C# snippets:: FRAG = ''' namespace Moo { public class Test { public static int Main(string[] args) { return 0; } } }''' def configure(conf): conf.check(features='cs', fragment=FRAG, compile_filename='test.cs', gen='test.exe', type='exe', csflags=['-pkg:gtk-sharp-2.0'], msg='Checking for Gtksharp support') """ from waflib import Utils, Task, Options, Logs, Errors from waflib.TaskGen import before_method, after_method, feature from waflib.Tools import ccroot from waflib.Configure import conf ccroot.USELIB_VARS['cs'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) ccroot.lib_patterns['csshlib'] = ['%s'] @feature('cs') @before_method('process_source') def apply_cs(self): """ Create a C# task bound to the attribute *cs_task*. There can be only one C# task by task generator. """ cs_nodes = [] no_nodes = [] for x in self.to_nodes(self.source): if x.name.endswith('.cs'): cs_nodes.append(x) else: no_nodes.append(x) self.source = no_nodes bintype = getattr(self, 'type', self.gen.endswith('.dll') and 'library' or 'exe') self.cs_task = tsk = self.create_task('mcs', cs_nodes, self.path.find_or_declare(self.gen)) tsk.env.CSTYPE = '/target:%s' % bintype tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') if inst_to: # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) self.install_task = self.bld.install_files(inst_to, self.cs_task.outputs[:], env=self.env, chmod=mod) @feature('cs') @after_method('apply_cs') def use_cs(self): """ C# applications honor the **use** keyword:: def build(bld): bld(features='cs', source='My.cs', type='library', gen='my.dll', name='mylib') bld(features='cs', source='Hi.cs', includes='.', type='exe', gen='hi.exe', use='mylib', name='hi') """ names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except Errors.WafError: self.cs_task.env.append_value('CSFLAGS', '/reference:%s' % x) continue y.post() tsk = getattr(y, 'cs_task', None) or getattr(y, 'link_task', None) if not tsk: self.bld.fatal('cs task has no link task for use %r' % self) self.cs_task.dep_nodes.extend(tsk.outputs) # dependency self.cs_task.set_run_after(tsk) # order (redundant, the order is infered from the nodes inputs/outputs) self.cs_task.env.append_value('CSFLAGS', '/reference:%s' % tsk.outputs[0].abspath()) @feature('cs') @after_method('apply_cs', 'use_cs') def debug_cs(self): """ The C# targets may create .mdb or .pdb files:: def build(bld): bld(features='cs', source='My.cs', type='library', gen='my.dll', csdebug='full') # csdebug is a value in [True, 'full', 'pdbonly'] """ csdebug = getattr(self, 'csdebug', self.env.CSDEBUG) if not csdebug: return node = self.cs_task.outputs[0] if self.env.CS_NAME == 'mono': out = node.parent.find_or_declare(node.name + '.mdb') else: out = node.change_ext('.pdb') self.cs_task.outputs.append(out) try: self.install_task.source.append(out) except AttributeError: pass if csdebug == 'pdbonly': val = ['/debug+', '/debug:pdbonly'] elif csdebug == 'full': val = ['/debug+', '/debug:full'] else: val = ['/debug-'] self.cs_task.env.append_value('CSFLAGS', val) class mcs(Task.Task): """ Compile C# files """ color = 'YELLOW' run_str = '${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' def configure(conf): """ Find a C# compiler, set the variable MCS for the compiler and CS_NAME (mono or csc) """ csc = getattr(Options.options, 'cscbinary', None) if csc: conf.env.MCS = csc conf.find_program(['csc', 'mcs', 'gmcs'], var='MCS') conf.env.ASS_ST = '/r:%s' conf.env.RES_ST = '/resource:%s' conf.env.CS_NAME = 'csc' if str(conf.env.MCS).lower().find('mcs') > -1: conf.env.CS_NAME = 'mono' def options(opt): """ Add a command-line option for the configuration:: $ waf configure --with-csc-binary=/foo/bar/mcs """ opt.add_option('--with-csc-binary', type='string', dest='cscbinary') class fake_csshlib(Task.Task): """ Task used for reading a foreign .net assembly and adding the dependency on it """ color = 'YELLOW' inst_to = None def runnable_status(self): for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME @conf def read_csshlib(self, name, paths=[]): """ Read a foreign .net assembly for the *use* system:: def build(bld): bld.read_csshlib('ManagedLibrary.dll', paths=[bld.env.mylibrarypath]) bld(features='cs', source='Hi.cs', type='exe', gen='hi.exe', use='ManagedLibrary.dll') :param name: Name of the library :type name: string :param paths: Folders in which the library may be found :type paths: list of string :return: A task generator having the feature *fake_lib* which will call :py:func:`waflib.Tools.ccroot.process_lib` :rtype: :py:class:`waflib.TaskGen.task_gen` """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='csshlib') debian/waf-1.6/waflib/Tools/ar.py0000664000000000000000000000107512145744415013601 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) """ The **ar** program creates static libraries. This tool is almost always loaded from others (C, C++, D, etc) for static library support. """ from waflib.Configure import conf @conf def find_ar(conf): """Configuration helper used by C/C++ tools to enable the support for static libraries""" conf.load('ar') def configure(conf): """Find the ar program and set the default flags in ``conf.env.ARFLAGS``""" conf.find_program('ar', var='AR') conf.env.ARFLAGS = 'rcs' debian/waf-1.6/waflib/Tools/lua.py0000664000000000000000000000150212145744415013753 0ustar #!/usr/bin/env python # encoding: utf-8 # Sebastian Schlingmann, 2008 # Thomas Nagy, 2008-2010 (ita) """ Lua support. Compile *.lua* files into *.luac*:: def configure(conf): conf.load('lua') conf.env.LUADIR = '/usr/local/share/myapp/scripts/' def build(bld): bld(source='foo.lua') """ from waflib.TaskGen import extension from waflib import Task, Utils @extension('.lua') def add_lua(self, node): tsk = self.create_task('luac', node, node.change_ext('.luac')) inst_to = getattr(self, 'install_path', self.env.LUADIR and '${LUADIR}' or None) if inst_to: self.bld.install_files(inst_to, tsk.outputs) return tsk class luac(Task.Task): run_str = '${LUAC} -s -o ${TGT} ${SRC}' color = 'PINK' def configure(conf): """ Detect the luac compiler and set *conf.env.LUAC* """ conf.find_program('luac', var='LUAC') debian/waf-1.6/waflib/Tools/fc_scan.py0000664000000000000000000000627012145744415014575 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils, Task, TaskGen, Logs from waflib.TaskGen import feature, before_method, after_method, extension from waflib.Configure import conf INC_REGEX = """(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" MOD_REGEX = """(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" # TODO (DC) # - handle pre-processed files (FORTRANPPCOM in scons) # - handle multiple dialects # TODO (ita) understand what the above is supposed to mean ^^ re_inc = re.compile(INC_REGEX, re.I) re_use = re.compile(USE_REGEX, re.I) re_mod = re.compile(MOD_REGEX, re.I) class fortran_parser(object): """ This parser will return: * the nodes corresponding to the module names that will be produced * the nodes corresponding to the include files used * the module names used by the fortran file """ def __init__(self, incpaths): self.seen = [] """Files already parsed""" self.nodes = [] """List of :py:class:`waflib.Node.Node` representing the dependencies to return""" self.names = [] """List of module names to return""" self.incpaths = incpaths """List of :py:class:`waflib.Node.Node` representing the include paths""" def find_deps(self, node): """ Parse a fortran file to read the dependencies used and provided :param node: fortran file to read :type node: :py:class:`waflib.Node.Node` :return: lists representing the includes, the modules used, and the modules created by a fortran file :rtype: tuple of list of strings """ txt = node.read() incs = [] uses = [] mods = [] for line in txt.splitlines(): # line by line regexp search? optimize? m = re_inc.search(line) if m: incs.append(m.group(1)) m = re_use.search(line) if m: uses.append(m.group(1)) m = re_mod.search(line) if m: mods.append(m.group(1)) return (incs, uses, mods) def start(self, node): """ Start the parsing. Use the stack self.waiting to hold the nodes to iterate on :param node: fortran file :type node: :py:class:`waflib.Node.Node` """ self.waiting = [node] while self.waiting: nd = self.waiting.pop(0) self.iter(nd) def iter(self, node): """ Process a single file in the search for dependencies, extract the files used the modules used, and the modules provided. """ path = node.abspath() incs, uses, mods = self.find_deps(node) for x in incs: if x in self.seen: continue self.seen.append(x) self.tryfind_header(x) for x in uses: name = "USE@%s" % x if not name in self.names: self.names.append(name) for x in mods: name = "MOD@%s" % x if not name in self.names: self.names.append(name) def tryfind_header(self, filename): """ Try to find an include and add it the nodes to process :param filename: file name :type filename: string """ found = None for n in self.incpaths: found = n.find_resource(filename) if found: self.nodes.append(found) self.waiting.append(found) break if not found: if not filename in self.names: self.names.append(filename) debian/waf-1.6/waflib/Tools/xlcxx.py0000664000000000000000000000315312145744415014344 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_xlcxx(conf): """ Detect the Aix C++ compiler """ cxx = conf.find_program(['xlc++_r', 'xlc++'], var='CXX') cxx = conf.cmd_to_list(cxx) conf.get_xlc_version(cxx) conf.env.CXX_NAME = 'xlc++' conf.env.CXX = cxx @conf def xlcxx_common_flags(conf): """ Flags required for executing the Aix C++ compiler """ v = conf.env v['CXX_SRC_F'] = [] v['CXX_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CXX']: v['LINK_CXX'] = v['CXX'] v['CXXLNK_SRC_F'] = [] v['CXXLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' v['SONAME_ST'] = [] v['SHLIB_MARKER'] = [] v['STLIB_MARKER'] = [] # program v['LINKFLAGS_cxxprogram']= ['-Wl,-brtl'] v['cxxprogram_PATTERN'] = '%s' # shared library v['CXXFLAGS_cxxshlib'] = ['-fPIC'] v['LINKFLAGS_cxxshlib'] = ['-G', '-Wl,-brtl,-bexpfull'] v['cxxshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cxxstlib'] = [] v['cxxstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_xlcxx() conf.find_ar() conf.xlcxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/msvc.py0000664000000000000000000007362312145744415014157 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 (dv) # Tamas Pal, 2007 (folti) # Nicolas Mercier, 2009 """ Microsoft Visual C++/Intel C++ compiler support Usage:: $ waf configure --msvc_version="msvc 10.0,msvc 9.0" --msvc_target="x64" or:: def configure(conf): conf.env['MSVC_VERSIONS'] = ['msvc 10.0', 'msvc 9.0', 'msvc 8.0', 'msvc 7.1', 'msvc 7.0', 'msvc 6.0', 'wsdk 7.0', 'intel 11', 'PocketPC 9.0', 'Smartphone 8.0'] conf.env['MSVC_TARGETS'] = ['x64'] conf.load('msvc') or:: def configure(conf): conf.load('msvc', funs='no_autodetect') conf.check_lib_msvc('gdi32') conf.check_libs_msvc('kernel32 user32') def build(bld): tg = bld.program(source='main.c', target='app', use='KERNEL32 USER32 GDI32') Platforms and targets will be tested in the order they appear; the first good configuration will be used. Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64 Compilers supported: * msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 10.0 (Visual Studio 2010) * wsdk => Windows SDK, versions 6.0, 6.1, 7.0 * icl => Intel compiler, versions 9,10,11 * Smartphone => Compiler/SDK for Smartphone devices (armv4/v4i) * PocketPC => Compiler/SDK for PocketPC devices (armv4/v4i) To use WAF in a VS2008 Make file project (see http://code.google.com/p/waf/issues/detail?id=894) You may consider to set the environment variable "VS_UNICODE_OUTPUT" to nothing before calling waf. So in your project settings use something like 'cmd.exe /C "set VS_UNICODE_OUTPUT=& set PYTHONUNBUFFERED=true & waf build"'. cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" Setting PYTHONUNBUFFERED gives the unbuffered output. """ import os, sys, re, tempfile try: import _winreg except: try: import winreg as _winreg except: _winreg = None from waflib import Utils, TaskGen, Runner, Configure, Task, Options from waflib.Logs import debug, info, warn, error from waflib.TaskGen import after_method, before_method, feature from waflib.Configure import conf from waflib.Tools import ccroot, c, cxx, ar, winres g_msvc_systemlibs = ''' aclui activeds ad1 adptif adsiid advapi32 asycfilt authz bhsupp bits bufferoverflowu cabinet cap certadm certidl ciuuid clusapi comctl32 comdlg32 comsupp comsuppd comsuppw comsuppwd comsvcs credui crypt32 cryptnet cryptui d3d8thk daouuid dbgeng dbghelp dciman32 ddao35 ddao35d ddao35u ddao35ud delayimp dhcpcsvc dhcpsapi dlcapi dnsapi dsprop dsuiext dtchelp faultrep fcachdll fci fdi framedyd framedyn gdi32 gdiplus glauxglu32 gpedit gpmuuid gtrts32w gtrtst32hlink htmlhelp httpapi icm32 icmui imagehlp imm32 iphlpapi iprop kernel32 ksguid ksproxy ksuser libcmt libcmtd libcpmt libcpmtd loadperf lz32 mapi mapi32 mgmtapi minidump mmc mobsync mpr mprapi mqoa mqrt msacm32 mscms mscoree msdasc msimg32 msrating mstask msvcmrt msvcurt msvcurtd mswsock msxml2 mtx mtxdm netapi32 nmapinmsupp npptools ntdsapi ntdsbcli ntmsapi ntquery odbc32 odbcbcp odbccp32 oldnames ole32 oleacc oleaut32 oledb oledlgolepro32 opends60 opengl32 osptk parser pdh penter pgobootrun pgort powrprof psapi ptrustm ptrustmd ptrustu ptrustud qosname rasapi32 rasdlg rassapi resutils riched20 rpcndr rpcns4 rpcrt4 rtm rtutils runtmchk scarddlg scrnsave scrnsavw secur32 sensapi setupapi sfc shell32 shfolder shlwapi sisbkup snmpapi sporder srclient sti strsafe svcguid tapi32 thunk32 traffic unicows url urlmon user32 userenv usp10 uuid uxtheme vcomp vcompd vdmdbg version vfw32 wbemuuid webpost wiaguid wininet winmm winscard winspool winstrm wintrust wldap32 wmiutils wow32 ws2_32 wsnmp32 wsock32 wst wtsapi32 xaswitch xolehlp '''.split() """importlibs provided by MSVC/Platform SDK. Do NOT search them""" all_msvc_platforms = [ ('x64', 'amd64'), ('x86', 'x86'), ('ia64', 'ia64'), ('x86_amd64', 'amd64'), ('x86_ia64', 'ia64') ] """List of msvc platforms""" all_wince_platforms = [ ('armv4', 'arm'), ('armv4i', 'arm'), ('mipsii', 'mips'), ('mipsii_fp', 'mips'), ('mipsiv', 'mips'), ('mipsiv_fp', 'mips'), ('sh4', 'sh'), ('x86', 'cex86') ] """List of wince platforms""" all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'), ('Itanium', 'ia64')] """List of icl platforms""" def options(opt): opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') def setup_msvc(conf, versions): platforms = getattr(Options.options, 'msvc_targets', '').split(',') if platforms == ['']: platforms=Utils.to_list(conf.env['MSVC_TARGETS']) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] desired_versions = getattr(Options.options, 'msvc_version', '').split(',') if desired_versions == ['']: desired_versions = conf.env['MSVC_VERSIONS'] or [v for v,_ in versions][::-1] versiondict = dict(versions) for version in desired_versions: try: targets = dict(versiondict [version]) for target in platforms: try: arch,(p1,p2,p3) = targets[target] compiler,revision = version.rsplit(' ', 1) return compiler,revision,p1,p2,p3 except KeyError: continue except KeyError: continue conf.fatal('msvc: Impossible to find a valid architecture for building (in setup_msvc)') @conf def get_msvc_version(conf, compiler, version, target, vcvars): """ Create a bat file to obtain the location of the libraries :param compiler: ? :param version: ? :target: ? :vcvars: ? :return: the location of msvc, the location of include dirs, and the library paths :rtype: tuple of strings """ debug('msvc: get_msvc_version: %r %r %r', compiler, version, target) batfile = conf.bldnode.make_node('waf-print-msvc.bat') batfile.write("""@echo off set INCLUDE= set LIB= call "%s" %s echo PATH=%%PATH%% echo INCLUDE=%%INCLUDE%% echo LIB=%%LIB%% """ % (vcvars,target)) sout = conf.cmd_and_log(['cmd', '/E:on', '/V:on', '/C', batfile.abspath()]) lines = sout.splitlines() if not lines[0]: lines=lines[1:] for x in ('Setting environment', 'Setting SDK environment', 'Intel(R) C++ Compiler', 'Intel Parallel Studio'): if lines[0].find(x) != -1: break else: debug('msvc: get_msvc_version: %r %r %r -> not found', compiler, version, target) conf.fatal('msvc: Impossible to find a valid architecture for building (in get_msvc_version)') for line in lines[1:]: if line.startswith('PATH='): path = line[5:] MSVC_PATH = path.split(';') elif line.startswith('INCLUDE='): MSVC_INCDIR = [i for i in line[8:].split(';') if i] elif line.startswith('LIB='): MSVC_LIBDIR = [i for i in line[4:].split(';') if i] # Check if the compiler is usable at all. # The detection may return 64-bit versions even on 32-bit systems, and these would fail to run. env = {} env.update(os.environ) env.update(PATH = path) compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) cxx = conf.find_program(compiler_name, path_list=MSVC_PATH) cxx = conf.cmd_to_list(cxx) # delete CL if exists. because it could contain parameters wich can change cl's behaviour rather catastrophically. if 'CL' in env: del(env['CL']) try: try: conf.cmd_and_log(cxx + ['/help'], env=env) except Exception as e: debug('msvc: get_msvc_version: %r %r %r -> failure' % (compiler, version, target)) debug(str(e)) conf.fatal('msvc: cannot run the compiler (in get_msvc_version)') else: debug('msvc: get_msvc_version: %r %r %r -> OK', compiler, version, target) finally: conf.env[compiler_name] = '' return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) @conf def gather_wsdk_versions(conf, versions): """ Use winreg to add the msvc versions to the input list :param versions: list to modify :type versions: list """ version_pattern = re.compile('^v..?.?\...?.?') try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') except WindowsError: return index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue try: msvc_version = _winreg.OpenKey(all_versions, version) path,type = _winreg.QueryValueEx(msvc_version,'InstallationFolder') except WindowsError: continue if os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): targets = [] for target,arch in all_msvc_platforms: try: targets.append((target, (arch, conf.get_msvc_version('wsdk', version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd'))))) except conf.errors.ConfigurationError: pass versions.append(('wsdk ' + version[1:], targets)) def gather_wince_supported_platforms(): """ Checks SmartPhones SDKs :param versions: list to modify :type versions: list """ supported_wince_platforms = [] try: ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: try: ce_sdk = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') except WindowsError: ce_sdk = '' if not ce_sdk: return supported_wince_platforms ce_index = 0 while 1: try: sdk_device = _winreg.EnumKey(ce_sdk, ce_index) except WindowsError: break ce_index = ce_index + 1 sdk = _winreg.OpenKey(ce_sdk, sdk_device) try: path,type = _winreg.QueryValueEx(sdk, 'SDKRootDir') except WindowsError: try: path,type = _winreg.QueryValueEx(sdk,'SDKInformation') path,xml = os.path.split(path) except WindowsError: continue path=str(path) path,device = os.path.split(path) if not device: path,device = os.path.split(path) for arch,compiler in all_wince_platforms: platforms = [] if os.path.isdir(os.path.join(path, device, 'Lib', arch)): platforms.append((arch, compiler, os.path.join(path, device, 'Include', arch), os.path.join(path, device, 'Lib', arch))) if platforms: supported_wince_platforms.append((device, platforms)) return supported_wince_platforms def gather_msvc_detected_versions(): #Detected MSVC versions! version_pattern = re.compile('^(\d\d?\.\d\d?)(Exp)?$') detected_versions = [] for vcver,vcvar in [('VCExpress','Exp'), ('VisualStudio','')]: try: prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\'+vcver all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, prefix) except WindowsError: try: prefix = 'SOFTWARE\\Microsoft\\'+vcver all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, prefix) except WindowsError: continue index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 match = version_pattern.match(version) if not match: continue else: versionnumber = float(match.group(1)) detected_versions.append((versionnumber, version+vcvar, prefix+"\\"+version)) def fun(tup): return tup[0] try: detected_versions.sort(key = fun) except: # old python sort detected_versions.sort(lambda x,y: cmp(x[0], y[0])) return detected_versions @conf def gather_msvc_targets(conf, versions, version, vc_path): #Looking for normal MSVC compilers! targets = [] if os.path.isfile(os.path.join(vc_path, 'vcvarsall.bat')): for target,realtarget in all_msvc_platforms[::-1]: try: targets.append((target, (realtarget, conf.get_msvc_version('msvc', version, target, os.path.join(vc_path, 'vcvarsall.bat'))))) except conf.errors.ConfigurationError: pass elif os.path.isfile(os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat')): try: targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, 'x86', os.path.join(vc_path, 'Common7', 'Tools', 'vsvars32.bat'))))) except conf.errors.ConfigurationError: pass elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): try: targets.append(('x86', ('x86', conf.get_msvc_version('msvc', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat'))))) except conf.errors.ConfigurationError: pass versions.append(('msvc '+ version, targets)) @conf def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): #Looking for Win CE compilers! for device,platforms in supported_platforms: cetargets = [] for platform,compiler,include,lib in platforms: winCEpath = os.path.join(vc_path, 'ce') if not os.path.isdir(winCEpath): continue try: common_bindirs,_1,_2 = conf.get_msvc_version('msvc', version, 'x86', vsvars) except conf.errors.ConfigurationError: continue if os.path.isdir(os.path.join(winCEpath, 'lib', platform)): bindirs = [os.path.join(winCEpath, 'bin', compiler), os.path.join(winCEpath, 'bin', 'x86_'+compiler)] + common_bindirs incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] cetargets.append((platform, (platform, (bindirs,incdirs,libdirs)))) if cetargets: versions.append((device + ' ' + version, cetargets)) @conf def gather_msvc_versions(conf, versions): vc_paths = [] for (v,version,reg) in gather_msvc_detected_versions(): try: try: msvc_version = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") except WindowsError: msvc_version = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") path,type = _winreg.QueryValueEx(msvc_version, 'ProductDir') vc_paths.append((version, os.path.abspath(str(path)))) except WindowsError: continue wince_supported_platforms = gather_wince_supported_platforms() for version,vc_path in vc_paths: vs_path = os.path.dirname(vc_path) vsvars = os.path.join(vs_path, 'Common7', 'Tools', 'vsvars32.bat') if wince_supported_platforms and os.path.isfile(vsvars): conf.gather_wince_targets(versions, version, vc_path, vsvars, wince_supported_platforms) for version,vc_path in vc_paths: vs_path = os.path.dirname(vc_path) conf.gather_msvc_targets(versions, version, vc_path) @conf def gather_icl_versions(conf, versions): """ Checks ICL compilers :param versions: list to modify :type versions: list """ version_pattern = re.compile('^...?.?\....?.?') try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') except WindowsError: try: all_versions = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') except WindowsError: return index = 0 while 1: try: version = _winreg.EnumKey(all_versions, index) except WindowsError: break index = index + 1 if not version_pattern.match(version): continue targets = [] for target,arch in all_icl_platforms: try: if target=='intel64': targetDir='EM64T_NATIVE' else: targetDir=target _winreg.OpenKey(all_versions,version+'\\'+targetDir) icl_version=_winreg.OpenKey(all_versions,version) path,type=_winreg.QueryValueEx(icl_version,'ProductDir') if os.path.isfile(os.path.join(path,'bin','iclvars.bat')): try: targets.append((target,(arch,conf.get_msvc_version('intel',version,target,os.path.join(path,'bin','iclvars.bat'))))) except conf.errors.ConfigurationError: pass except WindowsError: pass for target,arch in all_icl_platforms: try: icl_version = _winreg.OpenKey(all_versions, version+'\\'+target) path,type = _winreg.QueryValueEx(icl_version,'ProductDir') if os.path.isfile(os.path.join(path, 'bin', 'iclvars.bat')): try: targets.append((target, (arch, conf.get_msvc_version('intel', version, target, os.path.join(path, 'bin', 'iclvars.bat'))))) except conf.errors.ConfigurationError: pass except WindowsError: continue major = version[0:2] versions.append(('intel ' + major, targets)) @conf def get_msvc_versions(conf): """ :return: list of compilers installed :rtype: list of string """ if not conf.env['MSVC_INSTALLED_VERSIONS']: lst = [] conf.gather_icl_versions(lst) conf.gather_wsdk_versions(lst) conf.gather_msvc_versions(lst) conf.env['MSVC_INSTALLED_VERSIONS'] = lst return conf.env['MSVC_INSTALLED_VERSIONS'] @conf def print_all_msvc_detected(conf): """ Print the contents of *conf.env.MSVC_INSTALLED_VERSIONS* """ for version,targets in conf.env['MSVC_INSTALLED_VERSIONS']: info(version) for target,l in targets: info("\t"+target) @conf def detect_msvc(conf): versions = get_msvc_versions(conf) return setup_msvc(conf, versions) @conf def find_lt_names_msvc(self, libname, is_static=False): """ Win32/MSVC specific code to glean out information from libtool la files. this function is not attached to the task_gen class """ lt_names=[ 'lib%s.la' % libname, '%s.la' % libname, ] for path in self.env['LIBPATH']: for la in lt_names: laf=os.path.join(path,la) dll=None if os.path.exists(laf): ltdict = Utils.read_la_file(laf) lt_libdir=None if ltdict.get('libdir', ''): lt_libdir = ltdict['libdir'] if not is_static and ltdict.get('library_names', ''): dllnames=ltdict['library_names'].split() dll=dllnames[0].lower() dll=re.sub('\.dll$', '', dll) return (lt_libdir, dll, False) elif ltdict.get('old_library', ''): olib=ltdict['old_library'] if os.path.exists(os.path.join(path,olib)): return (path, olib, True) elif lt_libdir != '' and os.path.exists(os.path.join(lt_libdir,olib)): return (lt_libdir, olib, True) else: return (None, olib, True) else: raise self.errors.WafError('invalid libtool object file: %s' % laf) return (None, None, None) @conf def libname_msvc(self, libname, is_static=False): lib = libname.lower() lib = re.sub('\.lib$','',lib) if lib in g_msvc_systemlibs: return lib lib=re.sub('^lib','',lib) if lib == 'm': return None (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) if lt_path != None and lt_libname != None: if lt_static == True: # file existance check has been made by find_lt_names return os.path.join(lt_path,lt_libname) if lt_path != None: _libpaths=[lt_path] + self.env['LIBPATH'] else: _libpaths=self.env['LIBPATH'] static_libs=[ 'lib%ss.lib' % lib, 'lib%s.lib' % lib, '%ss.lib' % lib, '%s.lib' %lib, ] dynamic_libs=[ 'lib%s.dll.lib' % lib, 'lib%s.dll.a' % lib, '%s.dll.lib' % lib, '%s.dll.a' % lib, 'lib%s_d.lib' % lib, '%s_d.lib' % lib, '%s.lib' %lib, ] libnames=static_libs if not is_static: libnames=dynamic_libs + static_libs for path in _libpaths: for libn in libnames: if os.path.exists(os.path.join(path, libn)): debug('msvc: lib found: %s' % os.path.join(path,libn)) return re.sub('\.lib$', '',libn) #if no lib can be found, just return the libname as msvc expects it self.fatal("The library %r could not be found" % libname) return re.sub('\.lib$', '', libname) @conf def check_lib_msvc(self, libname, is_static=False, uselib_store=None): """ Ideally we should be able to place the lib in the right env var, either STLIB or LIB, but we don't distinguish static libs from shared libs. This is ok since msvc doesn't have any special linker flag to select static libs (no env['STLIB_MARKER']) """ libn = self.libname_msvc(libname, is_static) if not uselib_store: uselib_store = libname.upper() if False and is_static: # disabled self.env['STLIB_' + uselib_store] = [libn] else: self.env['LIB_' + uselib_store] = [libn] @conf def check_libs_msvc(self, libnames, is_static=False): for libname in Utils.to_list(libnames): self.check_lib_msvc(libname, is_static) def configure(conf): """ Configuration methods to call for detecting msvc """ conf.autodetect() conf.find_msvc() conf.msvc_common_flags() conf.cc_load_tools() conf.cxx_load_tools() conf.cc_add_flags() conf.cxx_add_flags() conf.link_add_flags() conf.visual_studio_add_flags() @conf def no_autodetect(conf): conf.env.NO_MSVC_DETECT = 1 configure(conf) @conf def autodetect(conf): v = conf.env if v.NO_MSVC_DETECT: return compiler, version, path, includes, libdirs = conf.detect_msvc() v['PATH'] = path v['INCLUDES'] = includes v['LIBPATH'] = libdirs v['MSVC_COMPILER'] = compiler try: v['MSVC_VERSION'] = float(version) except: v['MSVC_VERSION'] = float(version[:-3]) def _get_prog_names(conf, compiler): if compiler=='intel': compiler_name = 'ICL' linker_name = 'XILINK' lib_name = 'XILIB' else: # assumes CL.exe compiler_name = 'CL' linker_name = 'LINK' lib_name = 'LIB' return compiler_name, linker_name, lib_name @conf def find_msvc(conf): """Due to path format limitations, limit operation only to native Win32. Yeah it sucks.""" if sys.platform == 'cygwin': conf.fatal('MSVC module does not work under cygwin Python!') # the autodetection is supposed to be performed before entering in this method v = conf.env path = v['PATH'] compiler = v['MSVC_COMPILER'] version = v['MSVC_VERSION'] compiler_name, linker_name, lib_name = _get_prog_names(conf, compiler) v.MSVC_MANIFEST = (compiler == 'msvc' and version >= 8) or (compiler == 'wsdk' and version >= 6) or (compiler == 'intel' and version >= 11) # compiler cxx = None if v['CXX']: cxx = v['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] cxx = conf.find_program(compiler_name, var='CXX', path_list=path) cxx = conf.cmd_to_list(cxx) # before setting anything, check if the compiler is really msvc env = dict(conf.environ) if path: env.update(PATH = ';'.join(path)) if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): conf.fatal('the msvc compiler could not be identified') # c/c++ compiler v['CC'] = v['CXX'] = cxx v['CC_NAME'] = v['CXX_NAME'] = 'msvc' # linker if not v['LINK_CXX']: link = conf.find_program(linker_name, path_list=path) if link: v['LINK_CXX'] = link else: conf.fatal('%s was not found (linker)' % linker_name) v['LINK'] = link if not v['LINK_CC']: v['LINK_CC'] = v['LINK_CXX'] # staticlib linker if not v['AR']: stliblink = conf.find_program(lib_name, path_list=path, var='AR') if not stliblink: return v['ARFLAGS'] = ['/NOLOGO'] # manifest tool. Not required for VS 2003 and below. Must have for VS 2005 and later if v.MSVC_MANIFEST: mt = conf.find_program('MT', path_list=path, var='MT') v['MTFLAGS'] = ['/NOLOGO'] conf.load('winres') if not conf.env['WINRC']: warn('Resource compiler not found. Compiling resource file is disabled') @conf def visual_studio_add_flags(self): """visual studio flags found in the system environment""" v = self.env try: v.prepend_value('INCLUDES', self.environ['INCLUDE'].split(';')) # notice the 'S' except: pass try: v.prepend_value('LIBPATH', self.environ['LIB'].split(';')) except: pass @conf def msvc_common_flags(conf): """ Setup the flags required for executing the msvc compiler The default is to allow a static and a shared library having the same name in the same directory, the static one being prefixed by 'lib'. If you feel that this is incorrect, just change the extension (issue #824):: bld.env.STLIB_ST = bld.env.SHLIB_ST = '%s.lib' bld.stlib(..., name='libfoo') bld.shlib(..., name='foo') """ v = conf.env v['DEST_BINFMT'] = 'pe' v.append_value('CFLAGS', ['/nologo']) v.append_value('CXXFLAGS', ['/nologo']) v['DEFINES_ST'] = '/D%s' v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['/c', '/Fo'] if v['MSVC_VERSION'] >= 8: v['CC_TGT_F']= ['/FC'] + v['CC_TGT_F'] v['CXX_SRC_F'] = '' v['CXX_TGT_F'] = ['/c', '/Fo'] if v['MSVC_VERSION'] >= 8: v['CXX_TGT_F']= ['/FC'] + v['CXX_TGT_F'] v['CPPPATH_ST'] = '/I%s' # template for adding include paths v['AR_TGT_F'] = v['CCLNK_TGT_F'] = v['CXXLNK_TGT_F'] = '/OUT:' # Subsystem specific flags v['CFLAGS_CONSOLE'] = v['CXXFLAGS_CONSOLE'] = ['/SUBSYSTEM:CONSOLE'] v['CFLAGS_NATIVE'] = v['CXXFLAGS_NATIVE'] = ['/SUBSYSTEM:NATIVE'] v['CFLAGS_POSIX'] = v['CXXFLAGS_POSIX'] = ['/SUBSYSTEM:POSIX'] v['CFLAGS_WINDOWS'] = v['CXXFLAGS_WINDOWS'] = ['/SUBSYSTEM:WINDOWS'] v['CFLAGS_WINDOWSCE'] = v['CXXFLAGS_WINDOWSCE'] = ['/SUBSYSTEM:WINDOWSCE'] # CRT specific flags v['CFLAGS_CRT_MULTITHREADED'] = v['CXXFLAGS_CRT_MULTITHREADED'] = ['/MT'] v['CFLAGS_CRT_MULTITHREADED_DLL'] = v['CXXFLAGS_CRT_MULTITHREADED_DLL'] = ['/MD'] v['CFLAGS_CRT_MULTITHREADED_DBG'] = v['CXXFLAGS_CRT_MULTITHREADED_DBG'] = ['/MTd'] v['CFLAGS_CRT_MULTITHREADED_DLL_DBG'] = v['CXXFLAGS_CRT_MULTITHREADED_DLL_DBG'] = ['/MDd'] # linker v['LIB_ST'] = '%s.lib' # template for adding shared libs v['LIBPATH_ST'] = '/LIBPATH:%s' # template for adding libpaths v['STLIB_ST'] = 'lib%s.lib' v['STLIBPATH_ST'] = '/LIBPATH:%s' v.append_value('LINKFLAGS', ['/NOLOGO']) if v['MSVC_MANIFEST']: v.append_value('LINKFLAGS', ['/MANIFEST']) # shared library v['CFLAGS_cshlib'] = [] v['CXXFLAGS_cxxshlib'] = [] v['LINKFLAGS_cshlib'] = v['LINKFLAGS_cxxshlib'] = ['/DLL'] v['cshlib_PATTERN'] = v['cxxshlib_PATTERN'] = '%s.dll' v['implib_PATTERN'] = '%s.lib' v['IMPLIB_ST'] = '/IMPLIB:%s' # static library v['LINKFLAGS_cstlib'] = [] v['cstlib_PATTERN'] = v['cxxstlib_PATTERN'] = 'lib%s.lib' # program v['cprogram_PATTERN'] = v['cxxprogram_PATTERN'] = '%s.exe' ####################################################################################################### ##### conf above, build below @after_method('apply_link') @feature('c', 'cxx') def apply_flags_msvc(self): """ Add additional flags implied by msvc, such as subsystems and pdb files:: def build(bld): bld.stlib(source='main.c', target='bar', subsystem='gruik') """ if self.env.CC_NAME != 'msvc' or not getattr(self, 'link_task', None): return is_static = isinstance(self.link_task, ccroot.stlink_task) subsystem = getattr(self, 'subsystem', '') if subsystem: subsystem = '/subsystem:%s' % subsystem flags = is_static and 'ARFLAGS' or 'LINKFLAGS' self.env.append_value(flags, subsystem) if not is_static: for f in self.env.LINKFLAGS: d = f.lower() if d[1:] == 'debug': pdbnode = self.link_task.outputs[0].change_ext('.pdb') self.link_task.outputs.append(pdbnode) try: self.install_task.source.append(pdbnode) except AttributeError: pass break # split the manifest file processing from the link task, like for the rc processing @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib') @after_method('apply_link') def apply_manifest(self): """ Special linker for MSVC with support for embedding manifests into DLL's and executables compiled by Visual Studio 2005 or probably later. Without the manifest file, the binaries are unusable. See: http://msdn2.microsoft.com/en-us/library/ms235542(VS.80).aspx """ if self.env.CC_NAME == 'msvc' and self.env.MSVC_MANIFEST and getattr(self, 'link_task', None): out_node = self.link_task.outputs[0] man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') self.link_task.outputs.append(man_node) self.link_task.do_manifest = True def exec_mf(self): """ Create the manifest file """ env = self.env mtool = env['MT'] if not mtool: return 0 self.do_manifest = False outfile = self.outputs[0].abspath() manifest = None for out_node in self.outputs: if out_node.name.endswith('.manifest'): manifest = out_node.abspath() break if manifest is None: # Should never get here. If we do, it means the manifest file was # never added to the outputs list, thus we don't have a manifest file # to embed, so we just return. return 0 # embedding mode. Different for EXE's and DLL's. # see: http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx mode = '' if 'cprogram' in self.generator.features or 'cxxprogram' in self.generator.features: mode = '1' elif 'cshlib' in self.generator.features or 'cxxshlib' in self.generator.features: mode = '2' debug('msvc: embedding manifest in mode %r' % mode) lst = [] lst.append(env['MT']) lst.extend(Utils.to_list(env['MTFLAGS'])) lst.extend(['-manifest', manifest]) lst.append('-outputresource:%s;%s' % (outfile, mode)) lst = [lst] return self.exec_command(*lst) def quote_response_command(self, flag): if flag.find(' ') > -1: for x in ('/LIBPATH:', '/IMPLIB:', '/OUT:', '/I'): if flag.startswith(x): flag = '%s"%s"' % (x, flag[len(x):]) break else: flag = '"%s"' % flag return flag def exec_response_command(self, cmd, **kw): # not public yet try: tmp = None if sys.platform.startswith('win') and isinstance(cmd, list) and len(' '.join(cmd)) >= 8192: program = cmd[0] #unquoted program name, otherwise exec_command will fail cmd = [self.quote_response_command(x) for x in cmd] (fd, tmp) = tempfile.mkstemp() os.write(fd, '\r\n'.join(i.replace('\\', '\\\\') for i in cmd[1:]).encode()) os.close(fd) cmd = [program, '@' + tmp] # no return here, that's on purpose ret = self.generator.bld.exec_command(cmd, **kw) finally: if tmp: try: os.remove(tmp) except: pass # anti-virus and indexers can keep the files open -_- return ret ########## stupid evil command modification: concatenate the tokens /Fx, /doc, and /x: with the next token def exec_command_msvc(self, *k, **kw): """ Change the command-line execution for msvc programs. Instead of quoting all the paths and keep using the shell, we can just join the options msvc is interested in """ if self.env['CC_NAME'] == 'msvc': if isinstance(k[0], list): lst = [] carry = '' for a in k[0]: if a == '/Fo' or a == '/doc' or a[-1] == ':': carry = a else: lst.append(carry + a) carry = '' k = [lst] if self.env['PATH']: env = dict(os.environ) env.update(PATH = ';'.join(self.env['PATH'])) kw['env'] = env bld = self.generator.bld try: if not kw.get('cwd', None): kw['cwd'] = bld.cwd except AttributeError: bld.cwd = kw['cwd'] = bld.variant_dir ret = self.exec_response_command(k[0], **kw) if not ret and getattr(self, 'do_manifest', None): ret = self.exec_mf() return ret for k in 'c cxx cprogram cxxprogram cshlib cxxshlib cstlib cxxstlib'.split(): cls = Task.classes.get(k, None) if cls: cls.exec_command = exec_command_msvc cls.exec_response_command = exec_response_command cls.quote_response_command = quote_response_command cls.exec_mf = exec_mf debian/waf-1.6/waflib/Tools/dbus.py0000664000000000000000000000403112145744415014127 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 """ Compile dbus files with **dbus-binding-tool** Typical usage:: def options(opt): opt.load('compiler_c dbus') def configure(conf): conf.load('compiler_c dbus') def build(bld): tg = bld.program( includes = '.', source = bld.path.ant_glob('*.c'), target = 'gnome-hello') tg.add_dbus_file('test.xml', 'test_prefix', 'glib-server') """ from waflib import Task, Errors from waflib.TaskGen import taskgen_method, before_method @taskgen_method def add_dbus_file(self, filename, prefix, mode): """ Add a dbus file to the list of dbus files to process. Store them in the attribute *dbus_lst*. :param filename: xml file to compile :type filename: string :param prefix: dbus binding tool prefix (--prefix=prefix) :type prefix: string :param mode: dbus binding tool mode (--mode=mode) :type mode: string """ if not hasattr(self, 'dbus_lst'): self.dbus_lst = [] if not 'process_dbus' in self.meths: self.meths.append('process_dbus') self.dbus_lst.append([filename, prefix, mode]) @before_method('apply_core') def process_dbus(self): """ Process the dbus files stored in the attribute *dbus_lst* to create :py:class:`waflib.Tools.dbus.dbus_binding_tool` instances. """ for filename, prefix, mode in getattr(self, 'dbus_lst', []): node = self.path.find_resource(filename) if not node: raise Errors.WafError('file not found ' + filename) tsk = self.create_task('dbus_binding_tool', node, node.change_ext('.h')) tsk.env.DBUS_BINDING_TOOL_PREFIX = prefix tsk.env.DBUS_BINDING_TOOL_MODE = mode class dbus_binding_tool(Task.Task): """ Compile a dbus file """ color = 'BLUE' ext_out = ['.h'] run_str = '${DBUS_BINDING_TOOL} --prefix=${DBUS_BINDING_TOOL_PREFIX} --mode=${DBUS_BINDING_TOOL_MODE} --output=${TGT} ${SRC}' shell = True # temporary workaround for #795 def configure(conf): """ Detect the program dbus-binding-tool and set the *conf.env.DBUS_BINDING_TOOL* """ dbus_binding_tool = conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') debian/waf-1.6/waflib/Tools/c_aliases.py0000664000000000000000000000564612145744415015132 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) "base for all c/c++ programs and libraries" import os, sys, re from waflib import Utils, Build from waflib.Configure import conf def get_extensions(lst): """ :param lst: files to process :list lst: list of string or :py:class:`waflib.Node.Node` :return: list of file extensions :rtype: list of string """ ret = [] for x in Utils.to_list(lst): try: if not isinstance(x, str): x = x.name ret.append(x[x.rfind('.') + 1:]) except: pass return ret def sniff_features(**kw): """ Look at the source files and return the features for a task generator (mainly cc and cxx):: snif_features(source=['foo.c', 'foo.cxx'], type='shlib') # returns ['cxx', 'c', 'cxxshlib', 'cshlib'] :param source: source files to process :type source: list of string or :py:class:`waflib.Node.Node` :param type: object type in *program*, *shlib* or *stlib* :type type: string :return: the list of features for a task generator processing the source files :rtype: list of string """ exts = get_extensions(kw['source']) type = kw['_type'] feats = [] # watch the order, cxx will have the precedence if 'cxx' in exts or 'cpp' in exts or 'c++' in exts or 'cc' in exts or 'C' in exts: feats.append('cxx') if 'c' in exts or 'vala' in exts: feats.append('c') if 'd' in exts: feats.append('d') if 'java' in exts: feats.append('java') if 'java' in exts: return 'java' if type in ['program', 'shlib', 'stlib']: for x in feats: if x in ['cxx', 'd', 'c']: feats.append(x + type) return feats def set_features(kw, _type): kw['_type'] = _type kw['features'] = Utils.to_list(kw.get('features', [])) + Utils.to_list(sniff_features(**kw)) @conf def program(bld, *k, **kw): """ Alias for creating programs by looking at the file extensions:: def build(bld): bld.program(source='foo.c', target='app') # equivalent to: # bld(features='c cprogram', source='foo.c', target='app') """ set_features(kw, 'program') return bld(*k, **kw) @conf def shlib(bld, *k, **kw): """ Alias for creating shared libraries by looking at the file extensions:: def build(bld): bld.shlib(source='foo.c', target='app') # equivalent to: # bld(features='c cshlib', source='foo.c', target='app') """ set_features(kw, 'shlib') return bld(*k, **kw) @conf def stlib(bld, *k, **kw): """ Alias for creating static libraries by looking at the file extensions:: def build(bld): bld.stlib(source='foo.cpp', target='app') # equivalent to: # bld(features='cxx cxxstlib', source='foo.cpp', target='app') """ set_features(kw, 'stlib') return bld(*k, **kw) @conf def objects(bld, *k, **kw): """ Alias for creating object files by looking at the file extensions:: def build(bld): bld.objects(source='foo.c', target='app') # equivalent to: # bld(features='c', source='foo.c', target='app') """ set_features(kw, 'objects') return bld(*k, **kw) debian/waf-1.6/waflib/Tools/g95.py0000664000000000000000000000277512145744415013613 0ustar #! /usr/bin/env python # encoding: utf-8 # KWS 2010 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf @conf def find_g95(conf): fc = conf.find_program('g95', var='FC') fc = conf.cmd_to_list(fc) conf.get_g95_version(fc) conf.env.FC_NAME = 'G95' @conf def g95_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC'] v['FORTRANMODFLAG'] = ['-fmod=', ''] # template for module path v['FCFLAGS_DEBUG'] = ['-Werror'] # why not @conf def g95_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def g95_modifier_cygwin(conf): fc_config.fortran_modifier_cygwin(conf) @conf def g95_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def g95_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() g95_modifier_func = getattr(conf, 'g95_modifier_' + dest_os, None) if g95_modifier_func: g95_modifier_func() @conf def get_g95_version(conf, fc): """get the compiler version""" version_re = re.compile(r"g95\s*(?P\d*)\.(?P\d*)").search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('cannot determine g95 version') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_g95() conf.find_ar() conf.fc_flags() conf.g95_flags() conf.g95_modifier_platform() debian/waf-1.6/waflib/Tools/ruby.py0000664000000000000000000001271212145744415014160 0ustar #!/usr/bin/env python # encoding: utf-8 # daniel.svensson at purplescout.se 2008 # Thomas Nagy 2010 (ita) """ Support for Ruby extensions. A C/C++ compiler is required:: def options(opt): opt.load('compiler_c ruby') def configure(conf): conf.load('compiler_c ruby') conf.check_ruby_version((1,8,0)) conf.check_ruby_ext_devel() conf.check_ruby_module('libxml') def build(bld): bld( features = 'c cshlib rubyext', source = 'rb_mytest.c', target = 'mytest_ext', install_path = '${ARCHDIR_RUBY}') bld.install_files('${LIBDIR_RUBY}', 'Mytest.rb') """ import os from waflib import Task, Options, Utils from waflib.TaskGen import before_method, feature, after_method, Task, extension from waflib.Configure import conf @feature('rubyext') @before_method('apply_incpaths', 'apply_lib_vars', 'apply_bundle', 'apply_link') def init_rubyext(self): """ Add required variables for ruby extensions """ self.install_path = '${ARCHDIR_RUBY}' self.uselib = self.to_list(getattr(self, 'uselib', '')) if not 'RUBY' in self.uselib: self.uselib.append('RUBY') if not 'RUBYEXT' in self.uselib: self.uselib.append('RUBYEXT') @feature('rubyext') @before_method('apply_link', 'propagate_uselib') def apply_ruby_so_name(self): """ Strip the *lib* prefix from ruby extensions """ self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['rubyext_PATTERN'] @conf def check_ruby_version(self, minver=()): """ Checks if ruby is installed. If installed the variable RUBY will be set in environment. The ruby binary can be overridden by ``--with-ruby-binary`` command-line option. """ if Options.options.rubybinary: self.env.RUBY = Options.options.rubybinary else: self.find_program('ruby', var='RUBY') ruby = self.env.RUBY try: version = self.cmd_and_log([ruby, '-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() except: self.fatal('could not determine ruby version') self.env.RUBY_VERSION = version try: ver = tuple(map(int, version.split("."))) except: self.fatal('unsupported ruby version %r' % version) cver = '' if minver: if ver < minver: self.fatal('ruby is too old %r' % ver) cver = '.'.join([str(x) for x in minver]) else: cver = ver self.msg('Checking for ruby version %s' % str(minver or ''), cver) @conf def check_ruby_ext_devel(self): """ Check if a ruby extension can be created """ if not self.env.RUBY: self.fatal('ruby detection is required first') if not self.env.CC_NAME and not self.env.CXX_NAME: self.fatal('load a c/c++ compiler first') version = tuple(map(int, self.env.RUBY_VERSION.split("."))) def read_out(cmd): return Utils.to_list(self.cmd_and_log([self.env.RUBY, '-rrbconfig', '-e', cmd])) def read_config(key): return read_out('puts Config::CONFIG[%r]' % key) ruby = self.env['RUBY'] archdir = read_config('archdir') cpppath = archdir if version >= (1, 9, 0): ruby_hdrdir = read_config('rubyhdrdir') cpppath += ruby_hdrdir cpppath += [os.path.join(ruby_hdrdir[0], read_config('arch')[0])] self.check(header_name='ruby.h', includes=cpppath, errmsg='could not find ruby header file') self.env.LIBPATH_RUBYEXT = read_config('libdir') self.env.LIBPATH_RUBYEXT += archdir self.env.INCLUDES_RUBYEXT = cpppath self.env.CFLAGS_RUBYEXT = read_config('CCDLFLAGS') self.env.rubyext_PATTERN = '%s.' + read_config('DLEXT')[0] # ok this is really stupid, but the command and flags are combined. # so we try to find the first argument... flags = read_config('LDSHARED') while flags and flags[0][0] != '-': flags = flags[1:] # we also want to strip out the deprecated ppc flags if len(flags) > 1 and flags[1] == "ppc": flags = flags[2:] self.env.LINKFLAGS_RUBYEXT = flags self.env.LINKFLAGS_RUBYEXT += read_config('LIBS') self.env.LINKFLAGS_RUBYEXT += read_config('LIBRUBYARG_SHARED') if Options.options.rubyarchdir: self.env.ARCHDIR_RUBY = Options.options.rubyarchdir else: self.env.ARCHDIR_RUBY = read_config('sitearchdir')[0] if Options.options.rubylibdir: self.env.LIBDIR_RUBY = Options.options.rubylibdir else: self.env.LIBDIR_RUBY = read_config('sitelibdir')[0] @conf def check_ruby_module(self, module_name): """ Check if the selected ruby interpreter can require the given ruby module:: def configure(conf): conf.check_ruby_module('libxml') :param module_name: module :type module_name: string """ self.start_msg('Ruby module %s' % module_name) try: self.cmd_and_log([self.env['RUBY'], '-e', 'require \'%s\';puts 1' % module_name]) except: self.end_msg(False) self.fatal('Could not find the ruby module %r' % module_name) self.end_msg(True) @extension('.rb') def process(self, node): tsk = self.create_task('run_ruby', node) class run_ruby(Task.Task): """ Task to run ruby files detected by file extension .rb:: def options(opt): opt.load('ruby') def configure(ctx): ctx.check_ruby_version() def build(bld): bld.env['RBFLAGS'] = '-e puts "hello world"' bld(source='a_ruby_file.rb') """ run_str = '${RUBY} ${RBFLAGS} -I ${SRC[0].parent.abspath()} ${SRC}' def options(opt): """ Add the ``--with-ruby-archdir``, ``--with-ruby-libdir`` and ``--with-ruby-binary`` options """ opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') debian/waf-1.6/waflib/Tools/winres.py0000664000000000000000000000233412145744415014505 0ustar #!/usr/bin/env python # encoding: utf-8 # Brant Young, 2007 "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" from waflib import Task from waflib.TaskGen import extension @extension('.rc') def rc_file(self, node): """ Bind the .rc extension to a winrc task """ obj_ext = '.rc.o' if self.env['WINRC_TGT_F'] == '/fo': obj_ext = '.res' rctask = self.create_task('winrc', node, node.change_ext(obj_ext)) try: self.compiled_tasks.append(rctask) except AttributeError: self.compiled_tasks = [rctask] class winrc(Task.Task): """ Task for compiling resource files """ run_str = '${WINRC} ${WINRCFLAGS} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${WINRC_TGT_F} ${TGT} ${WINRC_SRC_F} ${SRC}' color = 'BLUE' def configure(conf): """ Detect the programs RC or windres, depending on the C/C++ compiler in use """ v = conf.env v['WINRC_TGT_F'] = '-o' v['WINRC_SRC_F'] = '-i' # find rc.exe if not conf.env.WINRC: if v.CC_NAME == 'msvc': conf.find_program('RC', var='WINRC', path_list = v['PATH']) v['WINRC_TGT_F'] = '/fo' v['WINRC_SRC_F'] = '' else: conf.find_program('windres', var='WINRC', path_list = v['PATH']) if not conf.env.WINRC: conf.fatal('winrc was not found!') v['WINRCFLAGS'] = [] debian/waf-1.6/waflib/Tools/suncc.py0000664000000000000000000000334112145744415014310 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) # Ralf Habacker, 2006 (rh) import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_scc(conf): """ Detect the Sun C compiler """ v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('cc', var='CC') if not cc: conf.fatal('Could not find a Sun C compiler') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-flags']) except: conf.fatal('%r is not a Sun compiler' % cc) v['CC'] = cc v['CC_NAME'] = 'sun' @conf def scc_common_flags(conf): """ Flags required for executing the sun C compiler """ v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['SONAME_ST'] = '-Wl,-h,%s' v['SHLIB_MARKER'] = '-Bdynamic' v['STLIB_MARKER'] = '-Bstatic' # program v['cprogram_PATTERN'] = '%s' # shared library v['CFLAGS_cshlib'] = ['-Kpic', '-DPIC'] v['LINKFLAGS_cshlib'] = ['-G'] v['cshlib_PATTERN'] = 'lib%s.so' # static lib v['LINKFLAGS_cstlib'] = ['-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_scc() conf.find_ar() conf.scc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/icpc.py0000664000000000000000000000162112145744415014112 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2009-2010 (ita) """ Detect the Intel C++ compiler """ import os, sys from waflib.Tools import ccroot, ar, gxx from waflib.Configure import conf @conf def find_icpc(conf): """ Find the program icpc, and execute it to ensure it really is icpc """ if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') v = conf.env cxx = None if v['CXX']: cxx = v['CXX'] elif 'CXX' in conf.environ: cxx = conf.environ['CXX'] if not cxx: cxx = conf.find_program('icpc', var='CXX') if not cxx: conf.fatal('Intel C++ Compiler (icpc) was not found') cxx = conf.cmd_to_list(cxx) conf.get_cc_version(cxx, icc=True) v['CXX'] = cxx v['CXX_NAME'] = 'icc' def configure(conf): conf.find_icpc() conf.find_ar() conf.gxx_common_flags() conf.gxx_modifier_platform() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/dmd.py0000664000000000000000000000341412145744415013742 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2008-2010 (ita) import sys from waflib.Tools import ar, d from waflib.Configure import conf @conf def find_dmd(conf): """ Find the program *dmd* or *ldc* and set the variable *D* """ conf.find_program(['dmd', 'ldc'], var='D') @conf def common_flags_ldc(conf): """ Set the D flags required by *ldc* """ v = conf.env v['DFLAGS'] = ['-d-version=Posix'] v['LINKFLAGS'] = [] v['DFLAGS_dshlib'] = ['-relocation-model=pic'] @conf def common_flags_dmd(conf): """ Set the flags required by *dmd* """ v = conf.env # _DFLAGS _DIMPORTFLAGS # Compiler is dmd so 'gdc' part will be ignored, just # ensure key is there, so wscript can append flags to it #v['DFLAGS'] = ['-version=Posix'] v['D_SRC_F'] = ['-c'] v['D_TGT_F'] = '-of%s' # linker v['D_LINKER'] = v['D'] v['DLNK_SRC_F'] = '' v['DLNK_TGT_F'] = '-of%s' v['DINC_ST'] = '-I%s' v['DSHLIB_MARKER'] = v['DSTLIB_MARKER'] = '' v['DSTLIB_ST'] = v['DSHLIB_ST'] = '-L-l%s' v['DSTLIBPATH_ST'] = v['DLIBPATH_ST'] = '-L-L%s' v['LINKFLAGS_dprogram']= ['-quiet'] v['DFLAGS_dshlib'] = ['-fPIC'] v['LINKFLAGS_dshlib'] = ['-L-shared'] v['DHEADER_ext'] = '.di' v.DFLAGS_d_with_header = ['-H', '-Hf'] v['D_HDR_F'] = '%s' def configure(conf): """ Configuration for dmd/ldc """ conf.find_dmd() if sys.platform == 'win32': out = conf.cmd_and_log([conf.env.D, '--help']) if out.find("D Compiler v2.") > -1: conf.fatal('dmd2 on Windows is not supported, use gdc or ldc instead') conf.load('ar') conf.load('d') conf.common_flags_dmd() conf.d_platform_flags() if str(conf.env.D).find('ldc') > -1: conf.common_flags_ldc() debian/waf-1.6/waflib/Tools/__init__.py0000664000000000000000000000010712145744415014731 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.6/waflib/Tools/c_preproc.py0000664000000000000000000006514212145744415015160 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ C/C++ preprocessor for finding dependencies Reasons for using the Waf preprocessor by default #. Some c/c++ extensions (Qt) require a custom preprocessor for obtaining the dependencies (.moc files) #. Not all compilers provide .d files for obtaining the dependencies (portability) #. A naive file scanner will not catch the constructs such as "#include foo()" #. A naive file scanner will catch unnecessary dependencies (change an unused header -> recompile everything) Regarding the speed concerns: * the preprocessing is performed only when files must be compiled * the macros are evaluated only for #if/#elif/#include * system headers are not scanned by default Now if you do not want the Waf preprocessor, the tool +gccdeps* uses the .d files produced during the compilation to track the dependencies (useful when used with the boost libraries). It only works with gcc >= 4.4 though. A dumb preprocessor is also available in the tool *c_dumbpreproc* """ # TODO: more varargs, pragma once import re, sys, os, string, traceback from waflib import Logs, Build, Utils, Errors from waflib.Logs import debug, error class PreprocError(Errors.WafError): pass POPFILE = '-' "Constant representing a special token used in :py:meth:`waflib.Tools.c_preproc.c_parser.start` iteration to switch to a header read previously" recursion_limit = 150 "Limit on the amount of files to read in the dependency scanner" go_absolute = False "Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" standard_includes = ['/usr/include'] if Utils.is_win32: standard_includes = [] use_trigraphs = 0 """Apply trigraph rules (False by default)""" strict_quotes = 0 """Reserve the "#include <>" quotes for system includes (do not search for those includes). False by default.""" g_optrans = { 'not':'!', 'and':'&&', 'bitand':'&', 'and_eq':'&=', 'or':'||', 'bitor':'|', 'or_eq':'|=', 'xor':'^', 'xor_eq':'^=', 'compl':'~', } """Operators such as and/or/xor for c++. Set an empty dict to disable.""" # ignore #warning and #error re_lines = re.compile( '^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*)\r*$', re.IGNORECASE | re.MULTILINE) """Match #include lines""" re_mac = re.compile("^[a-zA-Z_]\w*") """Match macro definitions""" re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') """Match macro functions""" re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE) """Match #pragma once statements""" re_nl = re.compile('\\\\\r*\n', re.MULTILINE) """Match newlines""" re_cpp = re.compile( r"""(/\*[^*]*\*+([^/*][^*]*\*+)*/)|//[^\n]*|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^/"'\\]*)""", re.MULTILINE) """Filter C/C++ comments""" trig_def = [('??'+a, b) for a, b in zip("=-/!'()<>", r'#~\|^[]{}')] """Trigraph definitions""" chr_esc = {'0':0, 'a':7, 'b':8, 't':9, 'n':10, 'f':11, 'v':12, 'r':13, '\\':92, "'":39} """Escape characters""" NUM = 'i' """Number token""" OP = 'O' """Operator token""" IDENT = 'T' """Identifier token""" STR = 's' """String token""" CHAR = 'c' """Character token""" tok_types = [NUM, STR, IDENT, OP] """Token types""" exp_types = [ r"""0[xX](?P[a-fA-F0-9]+)(?P[uUlL]*)|L*?'(?P(\\.|[^\\'])+)'|(?P\d+)[Ee](?P[+-]*?\d+)(?P[fFlL]*)|(?P\d*\.\d+)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P\d+\.\d*)([Ee](?P[+-]*?\d+))?(?P[fFlL]*)|(?P0*)(?P\d+)(?P[uUlL]*)""", r'L?"([^"\\]|\\.)*"', r'[a-zA-Z_]\w*', r'%:%:|<<=|>>=|\.\.\.|<<|<%|<:|<=|>>|>=|\+\+|\+=|--|->|-=|\*=|/=|%:|%=|%>|==|&&|&=|\|\||\|=|\^=|:>|!=|##|[\(\)\{\}\[\]<>\?\|\^\*\+&=:!#;,%/\-\?\~\.]', ] """Expression types""" re_clexer = re.compile('|'.join(["(?P<%s>%s)" % (name, part) for name, part in zip(tok_types, exp_types)]), re.M) """Match expressions into tokens""" accepted = 'a' """Parser state is *accepted*""" ignored = 'i' """Parser state is *ignored*, for example preprocessor lines in an #if 0 block""" undefined = 'u' """Parser state is *undefined* at the moment""" skipped = 's' """Parser state is *skipped*, for example preprocessor lines in a #elif 0 block""" def repl(m): """Replace function used with :py:attr:`waflib.Tools.c_preproc.re_cpp`""" s = m.group(1) if s: return ' ' return m.group(3) or '' def filter_comments(filename): """ Filter the comments from a c/h file, and return the preprocessor lines. The regexps :py:attr:`waflib.Tools.c_preproc.re_cpp`, :py:attr:`waflib.Tools.c_preproc.re_nl` and :py:attr:`waflib.Tools.c_preproc.re_lines` are used internally. :return: the preprocessor directives as a list of (keyword, line) :rtype: a list of string pairs """ # return a list of tuples : keyword, line code = Utils.readf(filename) if use_trigraphs: for (a, b) in trig_def: code = code.split(a).join(b) code = re_nl.sub('', code) code = re_cpp.sub(repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_lines, code)] prec = {} """ Operator precendence rules required for parsing expressions of the form:: #if 1 && 2 != 0 """ ops = ['* / %', '+ -', '<< >>', '< <= >= >', '== !=', '& | ^', '&& ||', ','] for x in range(len(ops)): syms = ops[x] for u in syms.split(): prec[u] = x def trimquotes(s): """ Remove the single quotes around an expression:: trimquotes("'test'") == "test" :param s: expression to transform :type s: string :rtype: string """ if not s: return '' s = s.rstrip() if s[0] == "'" and s[-1] == "'": return s[1:-1] return s def reduce_nums(val_1, val_2, val_op): """ Apply arithmetic rules to compute a result :param val1: input parameter :type val1: int or string :param val2: input parameter :type val2: int or string :param val_op: C operator in *+*, */*, *-*, etc :type val_op: string :rtype: int """ #print val_1, val_2, val_op # now perform the operation, make certain a and b are numeric try: a = 0 + val_1 except TypeError: a = int(val_1) try: b = 0 + val_2 except TypeError: b = int(val_2) d = val_op if d == '%': c = a%b elif d=='+': c = a+b elif d=='-': c = a-b elif d=='*': c = a*b elif d=='/': c = a/b elif d=='^': c = a^b elif d=='|': c = a|b elif d=='||': c = int(a or b) elif d=='&': c = a&b elif d=='&&': c = int(a and b) elif d=='==': c = int(a == b) elif d=='!=': c = int(a != b) elif d=='<=': c = int(a <= b) elif d=='<': c = int(a < b) elif d=='>': c = int(a > b) elif d=='>=': c = int(a >= b) elif d=='^': c = int(a^b) elif d=='<<': c = a<>': c = a>>b else: c = 0 return c def get_num(lst): """ Try to obtain a number from a list of tokens. The token types are defined in :py:attr:`waflib.Tools.ccroot.tok_types`. :param lst: list of preprocessor tokens :type lst: list of tuple (tokentype, value) :return: a pair containing the number and the rest of the list :rtype: tuple(value, list) """ if not lst: raise PreprocError("empty list for get_num") (p, v) = lst[0] if p == OP: if v == '(': count_par = 1 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 if count_par == 0: break elif v == '(': count_par += 1 i += 1 else: raise PreprocError("rparen expected %r" % lst) (num, _) = get_term(lst[1:i]) return (num, lst[i+1:]) elif v == '+': return get_num(lst[1:]) elif v == '-': num, lst = get_num(lst[1:]) return (reduce_nums('-1', num, '*'), lst) elif v == '!': num, lst = get_num(lst[1:]) return (int(not int(num)), lst) elif v == '~': return (~ int(num), lst) else: raise PreprocError("Invalid op token %r for get_num" % lst) elif p == NUM: return v, lst[1:] elif p == IDENT: # all macros should have been replaced, remaining identifiers eval to 0 return 0, lst[1:] else: raise PreprocError("Invalid token %r for get_num" % lst) def get_term(lst): """ Evaluate an expression recursively, for example:: 1+1+1 -> 2+1 -> 3 :param lst: list of tokens :type lst: list of tuple(token, value) :return: the value and the remaining tokens :rtype: value, list """ if not lst: raise PreprocError("empty list for get_term") num, lst = get_num(lst) if not lst: return (num, []) (p, v) = lst[0] if p == OP: if v == '&&' and not num: return (num, []) elif v == '||' and num: return (num, []) elif v == ',': # skip return get_term(lst[1:]) elif v == '?': count_par = 0 i = 1 while i < len(lst): (p, v) = lst[i] if p == OP: if v == ')': count_par -= 1 elif v == '(': count_par += 1 elif v == ':': if count_par == 0: break i += 1 else: raise PreprocError("rparen expected %r" % lst) if int(num): return get_term(lst[1:i]) else: return get_term(lst[i+1:]) else: num2, lst = get_num(lst[1:]) if not lst: # no more tokens to process num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) # operator precedence p2, v2 = lst[0] if p2 != OP: raise PreprocError("op expected %r" % lst) if prec[v2] >= prec[v]: num2 = reduce_nums(num, num2, v) return get_term([(NUM, num2)] + lst) else: num3, lst = get_num(lst[1:]) num3 = reduce_nums(num2, num3, v2) return get_term([(NUM, num), (p, v), (NUM, num3)] + lst) raise PreprocError("cannot reduce %r" % lst) def reduce_eval(lst): """ Take a list of tokens and output true or false for #if/#elif conditions. :param lst: a list of tokens :type lst: list of tuple(token, value) :return: a token :rtype: tuple(NUM, int) """ num, lst = get_term(lst) return (NUM, num) def stringize(lst): """ Merge a list of tokens into a string :param lst: a list of tokens :type lst: list of tuple(token, value) :rtype: string """ lst = [str(v2) for (p2, v2) in lst] return "".join(lst) def paste_tokens(t1, t2): """ Token pasting works between identifiers, particular operators, and identifiers and numbers:: a ## b -> ab > ## = -> >= a ## 2 -> a2 :param t1: token :type t1: tuple(type, value) :param t2: token :type t2: tuple(type, value) """ p1 = None if t1[0] == OP and t2[0] == OP: p1 = OP elif t1[0] == IDENT and (t2[0] == IDENT or t2[0] == NUM): p1 = IDENT elif t1[0] == NUM and t2[0] == NUM: p1 = NUM if not p1: raise PreprocError('tokens do not make a valid paste %r and %r' % (t1, t2)) return (p1, t1[1] + t2[1]) def reduce_tokens(lst, defs, ban=[]): """ Replace the tokens in lst, using the macros provided in defs, and a list of macros that cannot be re-applied :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :param ban: macros that cannot be substituted (recursion is not allowed) :type ban: list of string :return: the new list of tokens :rtype: value, list """ i = 0 while i < len(lst): (p, v) = lst[i] if p == IDENT and v == "defined": del lst[i] if i < len(lst): (p2, v2) = lst[i] if p2 == IDENT: if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) elif p2 == OP and v2 == '(': del lst[i] (p2, v2) = lst[i] del lst[i] # remove the ident, and change the ) for the value if v2 in defs: lst[i] = (NUM, 1) else: lst[i] = (NUM, 0) else: raise PreprocError("Invalid define expression %r" % lst) elif p == IDENT and v in defs: if isinstance(defs[v], str): a, b = extract_macro(defs[v]) defs[v] = b macro_def = defs[v] to_add = macro_def[1] if isinstance(macro_def[0], list): # macro without arguments del lst[i] for x in range(len(to_add)): lst.insert(i, to_add[x]) i += 1 else: # collect the arguments for the funcall args = [] del lst[i] if i >= len(lst): raise PreprocError("expected '(' after %r (got nothing)" % v) (p2, v2) = lst[i] if p2 != OP or v2 != '(': raise PreprocError("expected '(' after %r" % v) del lst[i] one_param = [] count_paren = 0 while i < len(lst): p2, v2 = lst[i] del lst[i] if p2 == OP and count_paren == 0: if v2 == '(': one_param.append((p2, v2)) count_paren += 1 elif v2 == ')': if one_param: args.append(one_param) break elif v2 == ',': if not one_param: raise PreprocError("empty param in funcall %s" % p) args.append(one_param) one_param = [] else: one_param.append((p2, v2)) else: one_param.append((p2, v2)) if v2 == '(': count_paren += 1 elif v2 == ')': count_paren -= 1 else: raise PreprocError('malformed macro') # substitute the arguments within the define expression accu = [] arg_table = macro_def[0] j = 0 while j < len(to_add): (p2, v2) = to_add[j] if p2 == OP and v2 == '#': # stringize is for arguments only if j+1 < len(to_add) and to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] accu.append((STR, stringize(toks))) j += 1 else: accu.append((p2, v2)) elif p2 == OP and v2 == '##': # token pasting, how can man invent such a complicated system? if accu and j+1 < len(to_add): # we have at least two tokens t1 = accu[-1] if to_add[j+1][0] == IDENT and to_add[j+1][1] in arg_table: toks = args[arg_table[to_add[j+1][1]]] if toks: accu[-1] = paste_tokens(t1, toks[0]) #(IDENT, accu[-1][1] + toks[0][1]) accu.extend(toks[1:]) else: # error, case "a##" accu.append((p2, v2)) accu.extend(toks) elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': # TODO not sure # first collect the tokens va_toks = [] st = len(macro_def[0]) pt = len(args) for x in args[pt-st+1:]: va_toks.extend(x) va_toks.append((OP, ',')) if va_toks: va_toks.pop() # extra comma if len(accu)>1: (p3, v3) = accu[-1] (p4, v4) = accu[-2] if v3 == '##': # remove the token paste accu.pop() if v4 == ',' and pt < st: # remove the comma accu.pop() accu += va_toks else: accu[-1] = paste_tokens(t1, to_add[j+1]) j += 1 else: # Invalid paste, case "##a" or "b##" accu.append((p2, v2)) elif p2 == IDENT and v2 in arg_table: toks = args[arg_table[v2]] reduce_tokens(toks, defs, ban+[v]) accu.extend(toks) else: accu.append((p2, v2)) j += 1 reduce_tokens(accu, defs, ban+[v]) for x in range(len(accu)-1, -1, -1): lst.insert(i, accu[x]) i += 1 def eval_macro(lst, defs): """ Reduce the tokens by :py:func:`waflib.Tools.c_preproc.reduce_tokens` and try to return a 0/1 result by :py:func:`waflib.Tools.c_preproc.reduce_eval`. :param lst: list of tokens :type lst: list of tuple(token, value) :param defs: macro definitions :type defs: dict :rtype: int """ reduce_tokens(lst, defs, []) if not lst: raise PreprocError("missing tokens to evaluate") (p, v) = reduce_eval(lst) return int(v) != 0 def extract_macro(txt): """ Process a macro definition of the form:: #define f(x, y) x * y into a function or a simple macro without arguments :param txt: expression to exact a macro definition from :type txt: string :return: a tuple containing the name, the list of arguments and the replacement :rtype: tuple(string, [list, list]) """ t = tokenize(txt) if re_fun.search(txt): p, name = t[0] p, v = t[1] if p != OP: raise PreprocError("expected open parenthesis") i = 1 pindex = 0 params = {} prev = '(' while 1: i += 1 p, v = t[i] if prev == '(': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == ')': break else: raise PreprocError("unexpected token (3)") elif prev == IDENT: if p == OP and v == ',': prev = v elif p == OP and v == ')': break else: raise PreprocError("comma or ... expected") elif prev == ',': if p == IDENT: params[v] = pindex pindex += 1 prev = p elif p == OP and v == '...': raise PreprocError("not implemented (1)") else: raise PreprocError("comma or ... expected (2)") elif prev == '...': raise PreprocError("not implemented (2)") else: raise PreprocError("unexpected else") #~ print (name, [params, t[i+1:]]) return (name, [params, t[i+1:]]) else: (p, v) = t[0] return (v, [[], t[1:]]) re_include = re.compile('^\s*(<(?P.*)>|"(?P.*)")') def extract_include(txt, defs): """ Process a line in the form:: #include foo :param txt: include line to process :type txt: string :param defs: macro definitions :type defs: dict :return: the file name :rtype: string """ m = re_include.search(txt) if m: if m.group('a'): return '<', m.group('a') if m.group('b'): return '"', m.group('b') # perform preprocessing and look at the result, it must match an include toks = tokenize(txt) reduce_tokens(toks, defs, ['waf_include']) if not toks: raise PreprocError("could not parse include %s" % txt) if len(toks) == 1: if toks[0][0] == STR: return '"', toks[0][1] else: if toks[0][1] == '<' and toks[-1][1] == '>': return stringize(toks).lstrip('<').rstrip('>') raise PreprocError("could not parse include %s." % txt) def parse_char(txt): """ Parse a c character :param txt: character to parse :type txt: string :return: a character literal :rtype: string """ if not txt: raise PreprocError("attempted to parse a null char") if txt[0] != '\\': return ord(txt) c = txt[1] if c == 'x': if len(txt) == 4 and txt[3] in string.hexdigits: return int(txt[2:], 16) return int(txt[2:], 16) elif c.isdigit(): if c == '0' and len(txt)==2: return 0 for i in 3, 2, 1: if len(txt) > i and txt[1:1+i].isdigit(): return (1+i, int(txt[1:1+i], 8)) else: try: return chr_esc[c] except KeyError: raise PreprocError("could not parse char literal '%s'" % txt) @Utils.run_once def tokenize(s): """ Convert a string into a list of tokens (shlex.split does not apply to c/c++/d) :param s: input to tokenize :type s: string :return: a list of tokens :rtype: list of tuple(token, value) """ # the same headers are read again and again - 10% improvement on preprocessing the samba headers ret = [] for match in re_clexer.finditer(s): m = match.group for name in tok_types: v = m(name) if v: if name == IDENT: try: v = g_optrans[v]; name = OP except KeyError: # c++ specific if v.lower() == "true": v = 1 name = NUM elif v.lower() == "false": v = 0 name = NUM elif name == NUM: if m('oct'): v = int(v, 8) elif m('hex'): v = int(m('hex'), 16) elif m('n0'): v = m('n0') else: v = m('char') if v: v = parse_char(v) else: v = m('n2') or m('n4') elif name == OP: if v == '%:': v = '#' elif v == '%:%:': v = '##' elif name == STR: # remove the quotes around the string v = v[1:-1] ret.append((name, v)) break return ret @Utils.run_once def define_name(line): """ :param line: define line :type line: string :rtype: string :return: the define name """ return re_mac.match(line).group(0) class c_parser(object): """ Used by :py:func:`waflib.Tools.c_preproc.scan` to parse c/h files. Note that by default, only project headers are parsed. """ def __init__(self, nodepaths=None, defines=None): self.lines = [] """list of lines read""" if defines is None: self.defs = {} else: self.defs = dict(defines) # make a copy self.state = [] self.count_files = 0 self.currentnode_stack = [] self.nodepaths = nodepaths or [] """Include paths""" self.nodes = [] """List of :py:class:`waflib.Node.Node` found so far""" self.names = [] """List of file names that could not be matched by any file""" self.curfile = '' """Current file""" self.ban_includes = set([]) """Includes that must not be read (#pragma once)""" def cached_find_resource(self, node, filename): """ Find a file from the input directory :param node: directory :type node: :py:class:`waflib.Node.Node` :param filename: header to find :type filename: string :return: the node if found, or None :rtype: :py:class:`waflib.Node.Node` """ try: nd = node.ctx.cache_nd except: nd = node.ctx.cache_nd = {} tup = (node, filename) try: return nd[tup] except KeyError: ret = node.find_resource(filename) if ret: if getattr(ret, 'children', None): ret = None elif ret.is_child_of(node.ctx.bldnode): tmp = node.ctx.srcnode.search(ret.path_from(node.ctx.bldnode)) if tmp and getattr(tmp, 'children', None): ret = None nd[tup] = ret return ret def tryfind(self, filename): """ Try to obtain a node from the filename based from the include paths. Will add the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to :py:attr:`waflib.Tools.c_preproc.c_parser.names` if no corresponding file is found. Called by :py:attr:`waflib.Tools.c_preproc.c_parser.start`. :param filename: header to find :type filename: string :return: the node if found :rtype: :py:class:`waflib.Node.Node` """ self.curfile = filename # for msvc it should be a for loop on the whole stack found = self.cached_find_resource(self.currentnode_stack[-1], filename) for n in self.nodepaths: if found: break found = self.cached_find_resource(n, filename) if found: # TODO the duplicates do not increase the no-op build times too much, but they may be worth removing self.nodes.append(found) if filename[-4:] != '.moc': self.addlines(found) else: if not filename in self.names: self.names.append(filename) return found def addlines(self, node): """ Add the lines from a header in the list of preprocessor lines to parse :param node: header :type node: :py:class:`waflib.Node.Node` """ self.currentnode_stack.append(node.parent) filepath = node.abspath() self.count_files += 1 if self.count_files > recursion_limit: # issue #812 raise PreprocError("recursion limit exceeded") pc = self.parse_cache debug('preproc: reading file %r', filepath) try: lns = pc[filepath] except KeyError: pass else: self.lines.extend(lns) return try: lines = filter_comments(filepath) lines.append((POPFILE, '')) lines.reverse() pc[filepath] = lines # cache the lines filtered self.lines.extend(lines) except IOError: raise PreprocError("could not read the file %s" % filepath) except Exception: if Logs.verbose > 0: error("parsing %s failed" % filepath) traceback.print_exc() def start(self, node, env): """ Preprocess a source file to obtain the dependencies, which are accumulated to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` and :py:attr:`waflib.Tools.c_preproc.c_parser.names`. :param node: source file :type node: :py:class:`waflib.Node.Node` :param env: config set containing additional defines to take into account :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ debug('preproc: scanning %s (in %s)', node.name, node.parent.name) bld = node.ctx try: self.parse_cache = bld.parse_cache except AttributeError: bld.parse_cache = {} self.parse_cache = bld.parse_cache self.addlines(node) # macros may be defined on the command-line, so they must be parsed as if they were part of the file if env['DEFINES']: try: lst = ['%s %s' % (x[0], trimquotes('='.join(x[1:]))) for x in [y.split('=') for y in env['DEFINES']]] lst.reverse() self.lines.extend([('define', x) for x in lst]) except AttributeError: # if the defines are invalid the compiler will tell the user pass while self.lines: (token, line) = self.lines.pop() if token == POPFILE: self.count_files -= 1 self.currentnode_stack.pop() continue try: ve = Logs.verbose if ve: debug('preproc: line is %s - %s state is %s', token, line, self.state) state = self.state # make certain we define the state if we are about to enter in an if block if token[:2] == 'if': state.append(undefined) elif token == 'endif': state.pop() # skip lines when in a dead 'if' branch, wait for the endif if token[0] != 'e': if skipped in self.state or ignored in self.state: continue if token == 'if': ret = eval_macro(tokenize(line), self.defs) if ret: state[-1] = accepted else: state[-1] = ignored elif token == 'ifdef': m = re_mac.match(line) if m and m.group(0) in self.defs: state[-1] = accepted else: state[-1] = ignored elif token == 'ifndef': m = re_mac.match(line) if m and m.group(0) in self.defs: state[-1] = ignored else: state[-1] = accepted elif token == 'include' or token == 'import': (kind, inc) = extract_include(line, self.defs) if inc in self.ban_includes: continue if token == 'import': self.ban_includes.add(inc) if ve: debug('preproc: include found %s (%s) ', inc, kind) if kind == '"' or not strict_quotes: self.tryfind(inc) elif token == 'elif': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: if eval_macro(tokenize(line), self.defs): state[-1] = accepted elif token == 'else': if state[-1] == accepted: state[-1] = skipped elif state[-1] == ignored: state[-1] = accepted elif token == 'define': try: self.defs[define_name(line)] = line except: raise PreprocError("Invalid define line %s" % line) elif token == 'undef': m = re_mac.match(line) if m and m.group(0) in self.defs: self.defs.__delitem__(m.group(0)) #print "undef %s" % name elif token == 'pragma': if re_pragma_once.match(line.lower()): self.ban_includes.add(self.curfile) except Exception as e: if Logs.verbose: debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack()) def scan(task): """ Get the dependencies using a c/c++ preprocessor, this is required for finding dependencies of the kind:: #include some_macro() This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example """ global go_absolute try: incn = task.generator.includes_nodes except AttributeError: raise Errors.WafError('%r is missing a feature such as "c", "cxx" or "includes": ' % task.generator) if go_absolute: nodepaths = incn + standard_includes else: nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] tmp = c_parser(nodepaths) tmp.start(task.inputs[0], task.env) if Logs.verbose: debug('deps: deps for %r: %r; unresolved %r' % (task.inputs, tmp.nodes, tmp.names)) return (tmp.nodes, tmp.names) debian/waf-1.6/waflib/Tools/asm.py0000664000000000000000000000315012145744415013753 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Assembly support, used by tools such as gas and nasm To declare targets using assembly:: def configure(conf): conf.load('gcc gas') def build(bld): bld( features='c cstlib asm', source = 'test.S', target = 'asmtest') bld( features='asm asmprogram', source = 'test.S', target = 'asmtest') Support for pure asm programs and libraries should also work:: def configure(conf): conf.load('nasm') conf.find_program('ld', 'ASLINK') def build(bld): bld( features='asm asmprogram', source = 'test.S', target = 'asmtest') """ import os, sys from waflib import Task, Utils import waflib.Task from waflib.Tools.ccroot import link_task, stlink_task from waflib.TaskGen import extension, feature class asm(Task.Task): """ Compile asm files by gas/nasm/yasm/... """ color = 'BLUE' run_str = '${AS} ${ASFLAGS} ${CPPPATH_ST:INCPATHS} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' @extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') def asm_hook(self, node): """ Bind the asm extension to the asm task :param node: input file :type node: :py:class:`waflib.Node.Node` """ return self.create_compiled_task('asm', node) class asmprogram(link_task): "Link object files into a c program" run_str = '${ASLINK} ${ASLINKFLAGS} ${ASLNK_TGT_F}${TGT} ${ASLNK_SRC_F}${SRC}' ext_out = ['.bin'] inst_to = '${BINDIR}' chmod = Utils.O755 class asmshlib(asmprogram): "Link object files into a c shared library" inst_to = '${LIBDIR}' class asmstlib(stlink_task): "Link object files into a c static library" pass # do not remove debian/waf-1.6/waflib/Tools/compiler_d.py0000664000000000000000000000313512145744415015313 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2010 (ita) """ Try to detect a D compiler from the list of supported compilers:: def options(opt): opt.load('compiler_d') def configure(cnf): cnf.load('compiler_d') def build(bld): bld.program(source='main.d', target='app') Only two D compilers are really present at the moment: * gdc, the ldc compiler having a very similar command-line interface * dmd """ import os, sys, imp, types from waflib import Utils, Configure, Options, Logs def configure(conf): """ Try to find a suitable D compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ for compiler in conf.options.dcheck.split(','): conf.env.stash() conf.start_msg('Checking for %r (d compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_cxx: %r' % e) else: if conf.env.D: conf.end_msg(conf.env.get_flat('D')) conf.env['COMPILER_D'] = compiler conf.env.D_COMPILER = conf.env.D # TODO remove this, left for compatibility break conf.end_msg(False) else: conf.fatal('no suitable d compiler was found') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-d-compiler=dmd """ d_compiler_opts = opt.add_option_group('D Compiler Options') d_compiler_opts.add_option('--check-d-compiler', default='gdc,dmd', action='store', help='check for the compiler [Default:gdc,dmd]', dest='dcheck') for d_compiler in ['gdc', 'dmd']: opt.load('%s' % d_compiler) debian/waf-1.6/waflib/Tools/compiler_fc.py0000664000000000000000000000401312145744415015454 0ustar #!/usr/bin/env python # encoding: utf-8 import os, sys, imp, types from waflib import Utils, Configure, Options, Logs, Errors from waflib.Tools import fc fc_compiler = { 'win32' : ['gfortran','ifort'], 'darwin' : ['gfortran', 'g95', 'ifort'], 'linux' : ['gfortran', 'g95', 'ifort'], 'java' : ['gfortran', 'g95', 'ifort'], 'default': ['gfortran'], 'aix' : ['gfortran'] } def __list_possible_compiler(platform): try: return fc_compiler[platform] except KeyError: return fc_compiler["default"] def configure(conf): """ Try to find a suitable Fortran compiler or raise a :py:class:`waflib.Errors.ConfigurationError`. """ try: test_for_compiler = conf.options.check_fc except AttributeError: conf.fatal("Add options(opt): opt.load('compiler_fc')") for compiler in test_for_compiler.split(): conf.env.stash() conf.start_msg('Checking for %r (fortran compiler)' % compiler) try: conf.load(compiler) except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_fortran: %r' % e) else: if conf.env['FC']: conf.end_msg(conf.env.get_flat('FC')) conf.env.COMPILER_FORTRAN = compiler break conf.end_msg(False) else: conf.fatal('could not configure a fortran compiler!') def options(opt): """ Restrict the compiler detection from the command-line:: $ waf configure --check-fortran-compiler=ifort """ opt.load_special_tools('fc_*.py') build_platform = Utils.unversioned_sys_platform() detected_platform = Options.platform possible_compiler_list = __list_possible_compiler(detected_platform) test_for_compiler = ' '.join(possible_compiler_list) fortran_compiler_opts = opt.add_option_group("Fortran Compiler Options") fortran_compiler_opts.add_option('--check-fortran-compiler', default="%s" % test_for_compiler, help='On this platform (%s) the following Fortran Compiler will be checked by default: "%s"' % (detected_platform, test_for_compiler), dest="check_fc") for compiler in test_for_compiler.split(): opt.load('%s' % compiler) debian/waf-1.6/waflib/Tools/errcheck.py0000664000000000000000000001511512145744415014765 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ errheck: Search for common mistakes There is a performance hit, so this tool is only loaded when running "waf -v" """ typos = { 'feature':'features', 'sources':'source', 'targets':'target', 'include':'includes', 'export_include':'export_includes', 'define':'defines', 'importpath':'includes', 'installpath':'install_path', } meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils import waflib.Tools.ccroot def check_same_targets(self): mp = Utils.defaultdict(list) uids = {} def check_task(tsk): if not isinstance(tsk, Task.Task): return for node in tsk.outputs: mp[node].append(tsk) try: uids[tsk.uid()].append(tsk) except: uids[tsk.uid()] = [tsk] for g in self.groups: for tg in g: try: for tsk in tg.tasks: check_task(tsk) except AttributeError: # raised if not a task generator, which should be uncommon check_task(tg) dupe = False for (k, v) in mp.items(): if len(v) > 1: dupe = True msg = '* Node %r is created by more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "") Logs.error(msg) for x in v: if Logs.verbose > 1: Logs.error(' %d. %r' % (1 + v.index(x), x.generator)) else: Logs.error(' %d. %r in %r' % (1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None))) if not dupe: for (k, v) in uids.items(): if len(v) > 1: Logs.error('* Several tasks use the same identifier. Please check the information on\n http://waf.googlecode.com/git/docs/apidocs/Task.html#waflib.Task.Task.uid') for tsk in v: Logs.error(' - object %r (%r) defined in %r' % (tsk.__class__.__name__, tsk, tsk.generator)) def check_invalid_constraints(self): feat = set([]) for x in list(TaskGen.feats.values()): feat.union(set(x)) for (x, y) in TaskGen.task_gen.prec.items(): feat.add(x) feat.union(set(y)) ext = set([]) for x in TaskGen.task_gen.mappings.values(): ext.add(x.__name__) invalid = ext & feat if invalid: Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method' % list(invalid)) # the build scripts have been read, so we can check for invalid after/before attributes on task classes for cls in list(Task.classes.values()): for x in ('before', 'after'): for y in Utils.to_list(getattr(cls, x, [])): if not Task.classes.get(y, None): Logs.error('Erroneous order constraint %r=%r on task class %r' % (x, y, cls.__name__)) if getattr(cls, 'rule', None): Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")' % cls.__name__) def replace(m): """ We could add properties, but they would not work in some cases: bld.program(...) requires 'source' in the attributes """ oldcall = getattr(Build.BuildContext, m) def call(self, *k, **kw): ret = oldcall(self, *k, **kw) for x in typos: if x in kw: err = True Logs.error('Fix the typo %r -> %r on %r' % (x, typos[x], ret)) return ret setattr(Build.BuildContext, m, call) def enhance_lib(): """ modify existing classes and methods """ for m in meths_typos: replace(m) # catch '..' in ant_glob patterns def ant_glob(self, *k, **kw): if k: lst=Utils.to_list(k[0]) for pat in lst: if '..' in pat.split('/'): Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'" % k[0]) if kw.get('remove', True): try: if self.is_child_of(self.ctx.bldnode) and not kw.get('quiet', False): Logs.error('Using ant_glob on the build folder (%r) is dangerous (quiet=True to disable this warning)' % self) except AttributeError: pass return self.old_ant_glob(*k, **kw) Node.Node.old_ant_glob = Node.Node.ant_glob Node.Node.ant_glob = ant_glob # catch conflicting ext_in/ext_out/before/after declarations old = Task.is_before def is_before(t1, t2): ret = old(t1, t2) if ret and old(t2, t1): Logs.error('Contradictory order constraints in classes %r %r' % (t1, t2)) return ret Task.is_before = is_before # check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose # so we only issue a warning def check_err_features(self): lst = self.to_list(self.features) if 'shlib' in lst: Logs.error('feature shlib -> cshlib, dshlib or cxxshlib') for x in ('c', 'cxx', 'd', 'fc'): if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]: Logs.error('%r features is probably missing %r' % (self, x)) TaskGen.feature('*')(check_err_features) # check for erroneous order constraints def check_err_order(self): if not hasattr(self, 'rule'): for x in ('before', 'after', 'ext_in', 'ext_out'): if hasattr(self, x): Logs.warn('Erroneous order constraint %r on non-rule based task generator %r' % (x, self)) else: for x in ('before', 'after'): for y in self.to_list(getattr(self, x, [])): if not Task.classes.get(y, None): Logs.error('Erroneous order constraint %s=%r on %r' % (x, y, self)) TaskGen.feature('*')(check_err_order) # check for @extension used with @feature/@before_method/@after_method def check_compile(self): check_invalid_constraints(self) try: ret = self.orig_compile() finally: check_same_targets(self) return ret Build.BuildContext.orig_compile = Build.BuildContext.compile Build.BuildContext.compile = check_compile # check for invalid build groups #914 def use_rec(self, name, **kw): try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: pass else: idx = self.bld.get_group_idx(self) odx = self.bld.get_group_idx(y) if odx > idx: msg = "Invalid 'use' across build groups:" if Logs.verbose > 1: msg += '\n target %r\n uses:\n %r' % (self, y) else: msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name) raise Errors.WafError(msg) self.orig_use_rec(name, **kw) TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec TaskGen.task_gen.use_rec = use_rec # check for env.append def getattri(self, name, default=None): if name == 'append' or name == 'add': raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique') elif name == 'prepend': raise Errors.WafError('env.prepend does not exist: use env.prepend_value') if name in self.__slots__: return object.__getattr__(self, name, default) else: return self[name] ConfigSet.ConfigSet.__getattr__ = getattri def options(opt): """ Add a few methods """ enhance_lib() def configure(conf): pass debian/waf-1.6/waflib/Tools/c_osx.py0000664000000000000000000001261512145744415014314 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy 2008-2010 """ MacOSX related tools """ import os, shutil, sys, platform from waflib import TaskGen, Task, Build, Options, Utils, Errors from waflib.TaskGen import taskgen_method, feature, after_method, before_method app_info = ''' CFBundlePackageType APPL CFBundleGetInfoString Created by Waf CFBundleSignature ???? NOTE THIS IS A GENERATED FILE, DO NOT MODIFY CFBundleExecutable %s ''' """ plist template """ @feature('c', 'cxx') def set_macosx_deployment_target(self): """ see WAF issue 285 and also and also http://trac.macports.org/ticket/17059 """ if self.env['MACOSX_DEPLOYMENT_TARGET']: os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env['MACOSX_DEPLOYMENT_TARGET'] elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ: if Utils.unversioned_sys_platform() == 'darwin': os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2]) @taskgen_method def create_bundle_dirs(self, name, out): """ Create bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp` """ bld = self.bld dir = out.parent.find_or_declare(name) dir.mkdir() macos = dir.find_or_declare(['Contents', 'MacOS']) macos.mkdir() return dir def bundle_name_for_output(out): name = out.name k = name.rfind('.') if k >= 0: name = name[:k] + '.app' else: name = name + '.app' return name @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macapp(self): """ To compile an executable into a Mac application (a .app), set its *mac_app* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_app = True) To force *all* executables to be transformed into Mac applications:: def build(bld): bld.env.MACAPP = True bld.shlib(source='a.c', target='foo') """ if self.env['MACAPP'] or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'MacOS', out.name]) self.apptask = self.create_task('macapp', self.link_task.outputs, n1) inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name self.bld.install_files(inst_to, n1, chmod=Utils.O755) if getattr(self, 'mac_resources', None): res_dir = n1.parent.parent.make_node('Resources') inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name for x in self.to_list(self.mac_resources): node = self.path.find_node(x) if not node: raise Errors.WafError('Missing mac_resource %r in %r' % (x, self)) parent = node.parent if os.path.isdir(node.abspath()): nodes = node.ant_glob('**') else: nodes = [node] for node in nodes: rel = node.path_from(parent) tsk = self.create_task('macapp', node, res_dir.make_node(rel)) self.bld.install_as(inst_to + '/%s' % rel, node) if getattr(self.bld, 'is_install', None): # disable the normal binary installation self.install_task.hasrun = Task.SKIP_ME @feature('cprogram', 'cxxprogram') @after_method('apply_link') def create_task_macplist(self): """ Create a :py:class:`waflib.Tools.c_osx.macplist` instance. """ if self.env['MACAPP'] or getattr(self, 'mac_app', False): out = self.link_task.outputs[0] name = bundle_name_for_output(out) dir = self.create_bundle_dirs(name, out) n1 = dir.find_or_declare(['Contents', 'Info.plist']) self.plisttask = plisttask = self.create_task('macplist', [], n1) if getattr(self, 'mac_plist', False): node = self.path.find_resource(self.mac_plist) if node: plisttask.inputs.append(node) else: plisttask.code = self.mac_plist else: plisttask.code = app_info % self.link_task.outputs[0].name inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name self.bld.install_files(inst_to, n1) @feature('cshlib', 'cxxshlib') @before_method('apply_link', 'propagate_uselib_vars') def apply_bundle(self): """ To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute:: def build(bld): bld.shlib(source='a.c', target='foo', mac_bundle = True) To force *all* executables to be transformed into bundles:: def build(bld): bld.env.MACBUNDLE = True bld.shlib(source='a.c', target='foo') """ if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False): self.env['LINKFLAGS_cshlib'] = self.env['LINKFLAGS_cxxshlib'] = [] # disable the '-dynamiclib' flag self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['macbundle_PATTERN'] use = self.use = self.to_list(getattr(self, 'use', [])) if not 'MACBUNDLE' in use: use.append('MACBUNDLE') app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources'] class macapp(Task.Task): """ Create mac applications """ color = 'PINK' def run(self): self.outputs[0].parent.mkdir() shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath()) class macplist(Task.Task): """ Create plist files """ color = 'PINK' ext_in = ['.bin'] def run(self): if getattr(self, 'code', None): txt = self.code else: txt = self.inputs[0].read() self.outputs[0].write(txt) debian/waf-1.6/waflib/Tools/irixcc.py0000664000000000000000000000264112145744415014460 0ustar #! /usr/bin/env python # imported from samba """ compiler definition for irix/MIPSpro cc compiler based on suncc.py from waf """ import os from waflib import Utils from waflib.Tools import ccroot, ar from waflib.Configure import conf @conf def find_irixcc(conf): v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('cc', var='CC') if not cc: conf.fatal('irixcc was not found') cc = conf.cmd_to_list(cc) try: conf.cmd_and_log(cc + ['-version']) except: conf.fatal('%r -version could not be executed' % cc) v['CC'] = cc v['CC_NAME'] = 'irix' @conf def irixcc_common_flags(conf): v = conf.env v['CC_SRC_F'] = '' v['CC_TGT_F'] = ['-c', '-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = '' v['CCLNK_TGT_F'] = ['-o'] v['LIB_ST'] = '-l%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l%s' v['STLIBPATH_ST'] = '-L%s' v['cprogram_PATTERN'] = '%s' v['cshlib_PATTERN'] = 'lib%s.so' v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_irixcc() conf.find_cpp() conf.find_ar() conf.irixcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/javaw.py0000664000000000000000000002637112145744415014315 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Java support Javac is one of the few compilers that behaves very badly: #. it outputs files where it wants to (-d is only for the package root) #. it recompiles files silently behind your back #. it outputs an undefined amount of files (inner classes) Remember that the compilation can be performed using Jython[1] rather than regular Python. Instead of running one of the following commands:: ./waf configure python waf configure You would have to run:: java -jar /path/to/jython.jar waf configure [1] http://www.jython.org/ """ import os, re, tempfile, shutil from waflib.Configure import conf from waflib import TaskGen, Task, Utils, Options, Build, Errors, Node, Logs from waflib.TaskGen import feature, before_method, after_method from waflib.Tools import ccroot ccroot.USELIB_VARS['javac'] = set(['CLASSPATH', 'JAVACFLAGS']) SOURCE_RE = '**/*.java' JAR_RE = '**/*' class_check_source = ''' public class Test { public static void main(String[] argv) { Class lib; if (argv.length < 1) { System.err.println("Missing argument"); System.exit(77); } try { lib = Class.forName(argv[0]); } catch (ClassNotFoundException e) { System.err.println("ClassNotFoundException"); System.exit(1); } lib = null; System.exit(0); } } ''' @feature('javac') @before_method('process_source') def apply_java(self): """ Create a javac task for compiling *.java files*. There can be only one javac task by task generator. """ Utils.def_attrs(self, jarname='', classpath='', sourcepath='.', srcdir='.', jar_mf_attributes={}, jar_mf_classpath=[]) nodes_lst = [] outdir = getattr(self, 'outdir', None) if outdir: if not isinstance(outdir, Node.Node): outdir = self.path.get_bld().make_node(self.outdir) else: outdir = self.path.get_bld() outdir.mkdir() self.outdir = outdir self.env['OUTDIR'] = outdir.abspath() self.javac_task = tsk = self.create_task('javac') tmp = [] srcdir = getattr(self, 'srcdir', '') if isinstance(srcdir, Node.Node): srcdir = [srcdir] for x in Utils.to_list(srcdir): if isinstance(x, Node.Node): y = x else: y = self.path.find_dir(x) if not y: self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) tmp.append(y) tsk.srcdir = tmp if getattr(self, 'compat', None): tsk.env.append_value('JAVACFLAGS', ['-source', self.compat]) if hasattr(self, 'sourcepath'): fold = [isinstance(x, Node.Node) and x or self.path.find_dir(x) for x in self.to_list(self.sourcepath)] names = os.pathsep.join([x.srcpath() for x in fold]) else: names = [x.srcpath() for x in tsk.srcdir] if names: tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) @feature('javac') @after_method('apply_java') def use_javac_files(self): """ Process the *use* attribute referring to other java compilations """ lst = [] self.uselib = self.to_list(getattr(self, 'uselib', [])) names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except: self.uselib.append(x) else: y.post() lst.append(y.jar_task.outputs[0].abspath()) self.javac_task.set_run_after(y.jar_task) if lst: self.env.append_value('CLASSPATH', lst) @feature('javac') @after_method('apply_java', 'propagate_uselib_vars', 'use_javac_files') def set_classpath(self): """ Set the CLASSPATH value on the *javac* task previously created. """ self.env.append_value('CLASSPATH', getattr(self, 'classpath', [])) for x in self.tasks: x.env.CLASSPATH = os.pathsep.join(self.env.CLASSPATH) + os.pathsep @feature('jar') @after_method('apply_java', 'use_javac_files') @before_method('process_source') def jar_files(self): """ Create a jar task. There can be only one jar task by task generator. """ destfile = getattr(self, 'destfile', 'test.jar') jaropts = getattr(self, 'jaropts', []) manifest = getattr(self, 'manifest', None) basedir = getattr(self, 'basedir', None) if basedir: if not isinstance(self.basedir, Node.Node): basedir = self.path.get_bld().make_node(basedir) else: basedir = self.path.get_bld() if not basedir: self.bld.fatal('Could not find the basedir %r for %r' % (self.basedir, self)) self.jar_task = tsk = self.create_task('jar_create') if manifest: jarcreate = getattr(self, 'jarcreate', 'cfm') node = self.path.find_node(manifest) tsk.dep_nodes.append(node) jaropts.insert(0, node.abspath()) else: jarcreate = getattr(self, 'jarcreate', 'cf') if not isinstance(destfile, Node.Node): destfile = self.path.find_or_declare(destfile) if not destfile: self.bld.fatal('invalid destfile %r for %r' % (destfile, self)) tsk.set_outputs(destfile) tsk.basedir = basedir jaropts.append('-C') jaropts.append(basedir.bldpath()) jaropts.append('.') tsk.env['JAROPTS'] = jaropts tsk.env['JARCREATE'] = jarcreate if getattr(self, 'javac_task', None): tsk.set_run_after(self.javac_task) @feature('jar') @after_method('jar_files') def use_jar_files(self): """ Process the *use* attribute to set the build order on the tasks created by another task generator. """ lst = [] self.uselib = self.to_list(getattr(self, 'uselib', [])) names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name for x in names: try: y = get(x) except: self.uselib.append(x) else: y.post() self.jar_task.run_after.update(y.tasks) class jar_create(Task.Task): """ Create a jar file """ color = 'GREEN' run_str = '${JAR} ${JARCREATE} ${TGT} ${JAROPTS}' def runnable_status(self): """ Wait for dependent tasks to be executed, then read the files to update the list of inputs. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global JAR_RE try: self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False) if id(x) != id(self.outputs[0])] except: raise Errors.WafError('Could not find the basedir %r for %r' % (self.basedir, self)) return super(jar_create, self).runnable_status() class javac(Task.Task): """ Compile java files """ color = 'BLUE' nocache = True """ The .class files cannot be put into a cache at the moment """ vars = ['CLASSPATH', 'JAVACFLAGS', 'JAVAC', 'OUTDIR'] """ The javac task will be executed again if the variables CLASSPATH, JAVACFLAGS, JAVAC or OUTDIR change. """ def runnable_status(self): """ Wait for dependent tasks to be complete, then read the file system to find the input nodes. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global SOURCE_RE self.inputs = [] for x in self.srcdir: self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) return super(javac, self).runnable_status() def run(self): """ Execute the javac compiler """ env = self.env gen = self.generator bld = gen.bld wd = bld.bldnode.abspath() def to_list(xx): if isinstance(xx, str): return [xx] return xx cmd = [] cmd.extend(to_list(env['JAVAC'])) cmd.extend(['-classpath']) cmd.extend(to_list(env['CLASSPATH'])) cmd.extend(['-d']) cmd.extend(to_list(env['OUTDIR'])) cmd.extend(to_list(env['JAVACFLAGS'])) files = [a.path_from(bld.bldnode) for a in self.inputs] # workaround for command line length limit: # http://support.microsoft.com/kb/830473 tmp = None try: if len(str(files)) + len(str(cmd)) > 8192: (fd, tmp) = tempfile.mkstemp(dir=bld.bldnode.abspath()) try: os.write(fd, '\n'.join(files).encode()) finally: if tmp: os.close(fd) if Logs.verbose: Logs.debug('runner: %r' % (cmd + files)) cmd.append('@' + tmp) else: cmd += files ret = self.exec_command(cmd, cwd=wd, env=env.env or None) finally: if tmp: os.unlink(tmp) return ret def post_run(self): """ """ for n in self.generator.outdir.ant_glob('**/*.class'): n.sig = Utils.h_file(n.abspath()) # careful with this self.generator.bld.task_sigs[self.uid()] = self.cache_sig def configure(self): """ Detect the javac, java and jar programs """ # If JAVA_PATH is set, we prepend it to the path list java_path = self.environ['PATH'].split(os.pathsep) v = self.env if 'JAVA_HOME' in self.environ: java_path = [os.path.join(self.environ['JAVA_HOME'], 'bin')] + java_path self.env['JAVA_HOME'] = [self.environ['JAVA_HOME']] for x in 'javac java jar'.split(): self.find_program(x, var=x.upper(), path_list=java_path) self.env[x.upper()] = self.cmd_to_list(self.env[x.upper()]) if 'CLASSPATH' in self.environ: v['CLASSPATH'] = self.environ['CLASSPATH'] if not v['JAR']: self.fatal('jar is required for making java packages') if not v['JAVAC']: self.fatal('javac is required for compiling java classes') v['JARCREATE'] = 'cf' # can use cvf v['JAVACFLAGS'] = [] @conf def check_java_class(self, classname, with_classpath=None): """ Check if the specified java class exists :param classname: class to check, like java.util.HashMap :type classname: string :param with_classpath: additional classpath to give :type with_classpath: string """ javatestdir = '.waf-javatest' classpath = javatestdir if self.env['CLASSPATH']: classpath += os.pathsep + self.env['CLASSPATH'] if isinstance(with_classpath, str): classpath += os.pathsep + with_classpath shutil.rmtree(javatestdir, True) os.mkdir(javatestdir) java_file = open(os.path.join(javatestdir, 'Test.java'), 'w') java_file.write(class_check_source) java_file.close() # Compile the source self.exec_command(self.env['JAVAC'] + [os.path.join(javatestdir, 'Test.java')], shell=False) # Try to run the app cmd = self.env['JAVA'] + ['-cp', classpath, 'Test', classname] self.to_log("%s\n" % str(cmd)) found = self.exec_command(cmd, shell=False) self.msg('Checking for java class %s' % classname, not found) shutil.rmtree(javatestdir, True) return found @conf def check_jni_headers(conf): """ Check for jni headers and libraries. On success the conf.env variables xxx_JAVA are added for use in C/C++ targets:: def options(opt): opt.load('compiler_c') def configure(conf): conf.load('compiler_c java') conf.check_jni_headers() def build(bld): bld.shlib(source='a.c', target='app', use='JAVA') """ if not conf.env.CC_NAME and not conf.env.CXX_NAME: conf.fatal('load a compiler first (gcc, g++, ..)') if not conf.env.JAVA_HOME: conf.fatal('set JAVA_HOME in the system environment') # jni requires the jvm javaHome = conf.env['JAVA_HOME'][0] dir = conf.root.find_dir(conf.env.JAVA_HOME[0] + '/include') if dir is None: conf.fatal('JAVA_HOME does not seem to be set properly') f = dir.ant_glob('**/(jni|jni_md).h') incDirs = [x.parent.abspath() for x in f] dir = conf.root.find_dir(conf.env.JAVA_HOME[0]) f = dir.ant_glob('**/*jvm.(so|dll|dylib)') libDirs = [x.parent.abspath() for x in f] or [javaHome] # On windows, we need both the .dll and .lib to link. On my JDK, they are # in different directories... f = dir.ant_glob('**/*jvm.(lib)') if f: libDirs = [[x, y.parent.abspath()] for x in libDirs for y in f] for d in libDirs: try: conf.check(header_name='jni.h', define_name='HAVE_JNI_H', lib='jvm', libpath=d, includes=incDirs, uselib_store='JAVA', uselib='JAVA') except: pass else: break else: conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) debian/waf-1.6/waflib/Tools/c_tests.py0000664000000000000000000001322512145744415014643 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Various configuration tests. """ from waflib import Task from waflib.Configure import conf from waflib.TaskGen import feature, before_method, after_method import sys LIB_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllexport) #else #define testEXPORT #endif testEXPORT int lib_func(void) { return 9; } ''' MAIN_CODE = ''' #ifdef _MSC_VER #define testEXPORT __declspec(dllimport) #else #define testEXPORT #endif testEXPORT int lib_func(void); int main(void) {return !(lib_func() == 9);} ''' @feature('link_lib_test') @before_method('process_source') def link_lib_test_fun(self): """ The configuration test :py:func:`waflib.Tools.ccroot.run_c_code` declares a unique task generator, so we need to create other task generators from here to check if the linker is able to link libraries. """ def write_test_file(task): task.outputs[0].write(task.generator.code) rpath = [] if getattr(self, 'add_rpath', False): rpath = [self.bld.path.get_bld().abspath()] mode = self.mode m = '%s %s' % (mode, mode) ex = self.test_exec and 'test_exec' or '' bld = self.bld bld(rule=write_test_file, target='test.' + mode, code=LIB_CODE) bld(rule=write_test_file, target='main.' + mode, code=MAIN_CODE) bld(features='%sshlib' % m, source='test.' + mode, target='test') bld(features='%sprogram %s' % (m, ex), source='main.' + mode, target='app', use='test', rpath=rpath) @conf def check_library(self, mode=None, test_exec=True): """ Check if libraries can be linked with the current linker. Uses :py:func:`waflib.Tools.c_tests.link_lib_test_fun`. :param mode: c or cxx or d :type mode: string """ if not mode: mode = 'c' if self.env.CXX: mode = 'cxx' self.check( compile_filename = [], features = 'link_lib_test', msg = 'Checking for libraries', mode = mode, test_exec = test_exec, ) ######################################################################################## INLINE_CODE = ''' typedef int foo_t; static %s foo_t static_foo () {return 0; } %s foo_t foo () { return 0; } ''' INLINE_VALUES = ['inline', '__inline__', '__inline'] @conf def check_inline(self, **kw): """ Check for the right value for inline macro. Define INLINE_MACRO to 1 if the define is found. If the inline macro is not 'inline', add a define to the ``config.h`` (#define inline __inline__) :param define_name: define INLINE_MACRO by default to 1 if the macro is defined :type define_name: string :param features: by default *c* or *cxx* depending on the compiler present :type features: list of string """ self.start_msg('Checking for inline') if not 'define_name' in kw: kw['define_name'] = 'INLINE_MACRO' if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx'] else: kw['features'] = ['c'] for x in INLINE_VALUES: kw['fragment'] = INLINE_CODE % (x, x) try: self.check(**kw) except self.errors.ConfigurationError: continue else: self.end_msg(x) if x != 'inline': self.define('inline', x, quote=False) return x self.fatal('could not use inline functions') ######################################################################################## LARGE_FRAGMENT = '#include \nint main() { return !(sizeof(off_t) >= 8); }\n' @conf def check_large_file(self, **kw): """ Check for large file support and define the macro HAVE_LARGEFILE The test is skipped on win32 systems (DEST_BINFMT == pe). :param define_name: define to set, by default *HAVE_LARGEFILE* :type define_name: string :param execute: execute the test (yes by default) :type execute: bool """ if not 'define_name' in kw: kw['define_name'] = 'HAVE_LARGEFILE' if not 'execute' in kw: kw['execute'] = True if not 'features' in kw: if self.env.CXX: kw['features'] = ['cxx', 'cxxprogram'] else: kw['features'] = ['c', 'cprogram'] kw['fragment'] = LARGE_FRAGMENT kw['msg'] = 'Checking for large file support' ret = True try: if self.env.DEST_BINFMT != 'pe': ret = self.check(**kw) except self.errors.ConfigurationError: pass else: if ret: return True kw['msg'] = 'Checking for -D_FILE_OFFSET_BITS=64' kw['defines'] = ['_FILE_OFFSET_BITS=64'] try: ret = self.check(**kw) except self.errors.ConfigurationError: pass else: self.define('_FILE_OFFSET_BITS', 64) return ret self.fatal('There is no support for large files') ######################################################################################## ENDIAN_FRAGMENT = ''' short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; ''' class grep_for_endianness(Task.Task): color = 'PINK' def run(self): txt = self.inputs[0].read(flags='rb').decode('iso8859-1') if txt.find('LiTTleEnDian') > -1: self.generator.tmp.append('little') elif txt.find('BIGenDianSyS') > -1: self.generator.tmp.append('big') else: return -1 @feature('grep_for_endianness') @after_method('process_source') def grep_for_endianness_fun(self): self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) @conf def check_endianness(self): """ Execute a configuration test to determine the endianness """ tmp = [] def check_msg(self): return tmp[0] self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', msg="Checking for endianness", define='ENDIANNESS', tmp=tmp, okmsg=check_msg) return tmp[0] debian/waf-1.6/waflib/Tools/d.py0000664000000000000000000000601412145744415013420 0ustar #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) # Thomas Nagy, 2007-2010 (ita) from waflib import Utils, Task, Errors from waflib.TaskGen import taskgen_method, feature, extension from waflib.Tools import d_scan, d_config from waflib.Tools.ccroot import link_task, stlink_task class d(Task.Task): "Compile a d file into an object file" color = 'GREEN' run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_SRC_F:SRC} ${D_TGT_F:TGT}' scan = d_scan.scan class d_with_header(d): "Compile a d file and generate a header" run_str = '${D} ${DFLAGS} ${DINC_ST:INCPATHS} ${D_HDR_F:tgt.outputs[1].bldpath()} ${D_SRC_F:SRC} ${D_TGT_F:tgt.outputs[0].bldpath()}' class d_header(Task.Task): "Compile d headers" color = 'BLUE' run_str = '${D} ${D_HEADER} ${SRC}' class dprogram(link_task): "Link object files into a d program" run_str = '${D_LINKER} ${LINKFLAGS} ${DLNK_SRC_F}${SRC} ${DLNK_TGT_F:TGT} ${RPATH_ST:RPATH} ${DSTLIB_MARKER} ${DSTLIBPATH_ST:STLIBPATH} ${DSTLIB_ST:STLIB} ${DSHLIB_MARKER} ${DLIBPATH_ST:LIBPATH} ${DSHLIB_ST:LIB}' inst_to = '${BINDIR}' chmod = Utils.O755 class dshlib(dprogram): "Link object files into a d shared library" inst_to = '${LIBDIR}' class dstlib(stlink_task): "Link object files into a d static library" pass # do not remove @extension('.d', '.di', '.D') def d_hook(self, node): """ Compile *D* files. To get .di files as well as .o files, set the following:: def build(bld): bld.program(source='foo.d', target='app', generate_headers=True) """ ext = Utils.destos_to_binfmt(self.env.DEST_OS) == 'pe' and 'obj' or 'o' out = '%s.%d.%s' % (node.name, self.idx, ext) def create_compiled_task(self, name, node): task = self.create_task(name, node, node.parent.find_or_declare(out)) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task if getattr(self, 'generate_headers', None): tsk = create_compiled_task(self, 'd_with_header', node) tsk.outputs.append(node.change_ext(self.env['DHEADER_ext'])) else: tsk = create_compiled_task(self, 'd', node) return tsk @taskgen_method def generate_header(self, filename, install_path=None): """ See feature request #104:: def build(bld): tg = bld.program(source='foo.d', target='app') tg.generate_header('blah.d') # is equivalent to: #tg = bld.program(source='foo.d', target='app', header_lst='blah.d') :param filename: header to create :type filename: string :param install_path: unused (TODO) """ try: self.header_lst.append([filename, install_path]) except AttributeError: self.header_lst = [[filename, install_path]] @feature('d') def process_header(self): """ Process the attribute 'header_lst' to create the d header compilation tasks:: def build(bld): bld.program(source='foo.d', target='app', header_lst='blah.d') """ for i in getattr(self, 'header_lst', []): node = self.path.find_resource(i[0]) if not node: raise Errors.WafError('file %r not found on d obj' % i[0]) self.create_task('d_header', node, node.change_ext('.di')) debian/waf-1.6/waflib/Tools/d_scan.py0000664000000000000000000001200712145744415014423 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Provide a scanner for finding dependencies on d files """ import re from waflib import Utils, Logs def filter_comments(filename): """ :param filename: d file name :type filename: string :rtype: list :return: a list of characters """ txt = Utils.readf(filename) i = 0 buf = [] max = len(txt) begin = 0 while i < max: c = txt[i] if c == '"' or c == "'": # skip a string or character literal buf.append(txt[begin:i]) delim = c i += 1 while i < max: c = txt[i] if c == delim: break elif c == '\\': # skip the character following backslash i += 1 i += 1 i += 1 begin = i elif c == '/': # try to replace a comment with whitespace buf.append(txt[begin:i]) i += 1 if i == max: break c = txt[i] if c == '+': # eat nesting /+ +/ comment i += 1 nesting = 1 c = None while i < max: prev = c c = txt[i] if prev == '/' and c == '+': nesting += 1 c = None elif prev == '+' and c == '/': nesting -= 1 if nesting == 0: break c = None i += 1 elif c == '*': # eat /* */ comment i += 1 c = None while i < max: prev = c c = txt[i] if prev == '*' and c == '/': break i += 1 elif c == '/': # eat // comment i += 1 while i < max and txt[i] != '\n': i += 1 else: # no comment begin = i - 1 continue i += 1 begin = i buf.append(' ') else: i += 1 buf.append(txt[begin:]) return buf class d_parser(object): """ Parser for d files """ def __init__(self, env, incpaths): #self.code = '' #self.module = '' #self.imports = [] self.allnames = [] self.re_module = re.compile("module\s+([^;]+)") self.re_import = re.compile("import\s+([^;]+)") self.re_import_bindings = re.compile("([^:]+):(.*)") self.re_import_alias = re.compile("[^=]+=(.+)") self.env = env self.nodes = [] self.names = [] self.incpaths = incpaths def tryfind(self, filename): """ Search file a file matching an module/import directive :param filename: file to read :type filename: string """ found = 0 for n in self.incpaths: found = n.find_resource(filename.replace('.', '/') + '.d') if found: self.nodes.append(found) self.waiting.append(found) break if not found: if not filename in self.names: self.names.append(filename) def get_strings(self, code): """ :param code: d code to parse :type code: string :return: the modules that the code uses :rtype: a list of match objects """ #self.imports = [] self.module = '' lst = [] # get the module name (if present) mod_name = self.re_module.search(code) if mod_name: self.module = re.sub('\s+', '', mod_name.group(1)) # strip all whitespaces # go through the code, have a look at all import occurrences # first, lets look at anything beginning with "import" and ending with ";" import_iterator = self.re_import.finditer(code) if import_iterator: for import_match in import_iterator: import_match_str = re.sub('\s+', '', import_match.group(1)) # strip all whitespaces # does this end with an import bindings declaration? # (import bindings always terminate the list of imports) bindings_match = self.re_import_bindings.match(import_match_str) if bindings_match: import_match_str = bindings_match.group(1) # if so, extract the part before the ":" (since the module declaration(s) is/are located there) # split the matching string into a bunch of strings, separated by a comma matches = import_match_str.split(',') for match in matches: alias_match = self.re_import_alias.match(match) if alias_match: # is this an alias declaration? (alias = module name) if so, extract the module name match = alias_match.group(1) lst.append(match) return lst def start(self, node): """ The parsing starts here :param node: input file :type node: :py:class:`waflib.Node.Node` """ self.waiting = [node] # while the stack is not empty, add the dependencies while self.waiting: nd = self.waiting.pop(0) self.iter(nd) def iter(self, node): """ Find all the modules that a file depends on, uses :py:meth:`waflib.Tools.d_scan.d_parser.tryfind` to process dependent files :param node: input file :type node: :py:class:`waflib.Node.Node` """ path = node.abspath() # obtain the absolute path code = "".join(filter_comments(path)) # read the file and filter the comments names = self.get_strings(code) # obtain the import strings for x in names: # optimization if x in self.allnames: continue self.allnames.append(x) # for each name, see if it is like a node or not self.tryfind(x) def scan(self): "look for .d/.di used by a d file" env = self.env gruik = d_parser(env, self.generator.includes_nodes) node = self.inputs[0] gruik.start(node) nodes = gruik.nodes names = gruik.names if Logs.verbose: Logs.debug('deps: deps for %s: %r; unresolved %r' % (str(node), nodes, names)) return (nodes, names) debian/waf-1.6/waflib/Tools/glib2.py0000664000000000000000000002777012145744415014210 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for GLib2 tools: * marshal * enums * gsettings """ import os from waflib import Task, Utils, Options, Errors, Logs from waflib.TaskGen import taskgen_method, before_method, after_method, feature ################## marshal files @taskgen_method def add_marshal_file(self, filename, prefix): """ Add a file to the list of marshal files to process. Store them in the attribute *marshal_list*. :param filename: xml file to compile :type filename: string :param prefix: marshal prefix (--prefix=prefix) :type prefix: string """ if not hasattr(self, 'marshal_list'): self.marshal_list = [] self.meths.append('process_marshal') self.marshal_list.append((filename, prefix)) @before_method('process_source') def process_marshal(self): """ Process the marshal files stored in the attribute *marshal_list* to create :py:class:`waflib.Tools.glib2.glib_genmarshal` instances. Add the c file created to the list of source to process. """ for f, prefix in getattr(self, 'marshal_list', []): node = self.path.find_resource(f) if not node: raise Errors.WafError('file not found %r' % f) h_node = node.change_ext('.h') c_node = node.change_ext('.c') task = self.create_task('glib_genmarshal', node, [h_node, c_node]) task.env.GLIB_GENMARSHAL_PREFIX = prefix self.source = self.to_nodes(getattr(self, 'source', [])) self.source.append(c_node) class glib_genmarshal(Task.Task): def run(self): bld = self.inputs[0].__class__.ctx get = self.env.get_flat cmd1 = "%s %s --prefix=%s --header > %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[0].abspath() ) ret = bld.exec_command(cmd1) if ret: return ret #print self.outputs[1].abspath() c = '''#include "%s"\n''' % self.outputs[0].name self.outputs[1].write(c) cmd2 = "%s %s --prefix=%s --body >> %s" % ( get('GLIB_GENMARSHAL'), self.inputs[0].srcpath(), get('GLIB_GENMARSHAL_PREFIX'), self.outputs[1].abspath() ) return bld.exec_command(cmd2) vars = ['GLIB_GENMARSHAL_PREFIX', 'GLIB_GENMARSHAL'] color = 'BLUE' ext_out = ['.h'] ########################## glib-mkenums @taskgen_method def add_enums_from_template(self, source='', target='', template='', comments=''): """ Add a file to the list of enum files to process. Store them in the attribute *enums_list*. :param source: enum file to process :type source: string :param target: target file :type target: string :param template: template file :type template: string :param comments: comments :type comments: string """ if not hasattr(self, 'enums_list'): self.enums_list = [] self.meths.append('process_enums') self.enums_list.append({'source': source, 'target': target, 'template': template, 'file-head': '', 'file-prod': '', 'file-tail': '', 'enum-prod': '', 'value-head': '', 'value-prod': '', 'value-tail': '', 'comments': comments}) @taskgen_method def add_enums(self, source='', target='', file_head='', file_prod='', file_tail='', enum_prod='', value_head='', value_prod='', value_tail='', comments=''): """ Add a file to the list of enum files to process. Store them in the attribute *enums_list*. :param source: enum file to process :type source: string :param target: target file :type target: string :param file_head: unused :param file_prod: unused :param file_tail: unused :param enum_prod: unused :param value_head: unused :param value_prod: unused :param value_tail: unused :param comments: comments :type comments: string """ if not hasattr(self, 'enums_list'): self.enums_list = [] self.meths.append('process_enums') self.enums_list.append({'source': source, 'template': '', 'target': target, 'file-head': file_head, 'file-prod': file_prod, 'file-tail': file_tail, 'enum-prod': enum_prod, 'value-head': value_head, 'value-prod': value_prod, 'value-tail': value_tail, 'comments': comments}) @before_method('process_source') def process_enums(self): """ Process the enum files stored in the attribute *enum_list* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. """ for enum in getattr(self, 'enums_list', []): task = self.create_task('glib_mkenums') env = task.env inputs = [] # process the source source_list = self.to_list(enum['source']) if not source_list: raise Errors.WafError('missing source ' + str(enum)) source_list = [self.path.find_resource(k) for k in source_list] inputs += source_list env['GLIB_MKENUMS_SOURCE'] = [k.abspath() for k in source_list] # find the target if not enum['target']: raise Errors.WafError('missing target ' + str(enum)) tgt_node = self.path.find_or_declare(enum['target']) if tgt_node.name.endswith('.c'): self.source.append(tgt_node) env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath() options = [] if enum['template']: # template, if provided template_node = self.path.find_resource(enum['template']) options.append('--template %s' % (template_node.abspath())) inputs.append(template_node) params = {'file-head' : '--fhead', 'file-prod' : '--fprod', 'file-tail' : '--ftail', 'enum-prod' : '--eprod', 'value-head' : '--vhead', 'value-prod' : '--vprod', 'value-tail' : '--vtail', 'comments': '--comments'} for param, option in params.items(): if enum[param]: options.append('%s %r' % (option, enum[param])) env['GLIB_MKENUMS_OPTIONS'] = ' '.join(options) # update the task instance task.set_inputs(inputs) task.set_outputs(tgt_node) class glib_mkenums(Task.Task): """ Process enum files """ run_str = '${GLIB_MKENUMS} ${GLIB_MKENUMS_OPTIONS} ${GLIB_MKENUMS_SOURCE} > ${GLIB_MKENUMS_TARGET}' color = 'PINK' ext_out = ['.h'] ######################################### gsettings @taskgen_method def add_settings_schemas(self, filename_list): """ Add settings files to process, add them to *settings_schema_files* :param filename_list: files :type filename_list: list of string """ if not hasattr(self, 'settings_schema_files'): self.settings_schema_files = [] if not isinstance(filename_list, list): filename_list = [filename_list] self.settings_schema_files.extend(filename_list) @taskgen_method def add_settings_enums(self, namespace, filename_list): """ This function may be called only once by task generator to set the enums namespace. :param namespace: namespace :type namespace: string :param filename_list: enum files to process :type filename_list: file list """ if hasattr(self, 'settings_enum_namespace'): raise Errors.WafError("Tried to add gsettings enums to '%s' more than once" % self.name) self.settings_enum_namespace = namespace if type(filename_list) != 'list': filename_list = [filename_list] self.settings_enum_files = filename_list def r_change_ext(self, ext): """ Change the extension from the *last* dot in the filename. The gsettings schemas often have names of the form org.gsettings.test.gschema.xml """ name = self.name k = name.rfind('.') if k >= 0: name = name[:k] + ext else: name = name + ext return self.parent.find_or_declare([name]) @feature('glib2') def process_settings(self): """ Process the schema files in *settings_schema_files* to create :py:class:`waflib.Tools.glib2.glib_mkenums` instances. The same files are validated through :py:class:`waflib.Tools.glib2.glib_validate_schema` tasks. """ enums_tgt_node = [] install_files = [] settings_schema_files = getattr(self, 'settings_schema_files', []) if settings_schema_files and not self.env['GLIB_COMPILE_SCHEMAS']: raise Errors.WafError ("Unable to process GSettings schemas - glib-compile-schemas was not found during configure") # 1. process gsettings_enum_files (generate .enums.xml) # if hasattr(self, 'settings_enum_files'): enums_task = self.create_task('glib_mkenums') source_list = self.settings_enum_files source_list = [self.path.find_resource(k) for k in source_list] enums_task.set_inputs(source_list) enums_task.env['GLIB_MKENUMS_SOURCE'] = [k.abspath() for k in source_list] target = self.settings_enum_namespace + '.enums.xml' tgt_node = self.path.find_or_declare(target) enums_task.set_outputs(tgt_node) enums_task.env['GLIB_MKENUMS_TARGET'] = tgt_node.abspath() enums_tgt_node = [tgt_node] install_files.append (tgt_node) options = '--comments "" --fhead "" --vhead " <@type@ id=\\"%s.@EnumName@\\">" --vprod " " --vtail " " --ftail "" ' % (self.settings_enum_namespace) enums_task.env['GLIB_MKENUMS_OPTIONS'] = options # 2. process gsettings_schema_files (validate .gschema.xml files) # for schema in settings_schema_files: schema_task = self.create_task ('glib_validate_schema') schema_node = self.path.find_resource(schema) if not schema_node: raise Errors.WafError("Cannot find the schema file '%s'" % schema) install_files.append(schema_node) source_list = enums_tgt_node + [schema_node] schema_task.set_inputs (source_list) schema_task.env['GLIB_COMPILE_SCHEMAS_OPTIONS'] = [("--schema-file=" + k.abspath()) for k in source_list] target_node = r_change_ext (schema_node, '.xml.valid') schema_task.set_outputs (target_node) schema_task.env['GLIB_VALIDATE_SCHEMA_OUTPUT'] = target_node.abspath() # 3. schemas install task def compile_schemas_callback(bld): if not bld.is_install: return Logs.pprint ('YELLOW','Updating GSettings schema cache') command = Utils.subst_vars("${GLIB_COMPILE_SCHEMAS} ${GSETTINGSSCHEMADIR}", bld.env) ret = self.bld.exec_command(command) if self.bld.is_install: if not self.env['GSETTINGSSCHEMADIR']: raise Errors.WafError ('GSETTINGSSCHEMADIR not defined (should have been set up automatically during configure)') if install_files: self.bld.install_files (self.env['GSETTINGSSCHEMADIR'], install_files) if not hasattr(self.bld, '_compile_schemas_registered'): self.bld.add_post_fun (compile_schemas_callback) self.bld._compile_schemas_registered = True class glib_validate_schema(Task.Task): """ Validate schema files """ run_str = 'rm -f ${GLIB_VALIDATE_SCHEMA_OUTPUT} && ${GLIB_COMPILE_SCHEMAS} --dry-run ${GLIB_COMPILE_SCHEMAS_OPTIONS} && touch ${GLIB_VALIDATE_SCHEMA_OUTPUT}' color = 'PINK' def configure(conf): """ Find the following programs: * *glib-genmarshal* and set *GLIB_GENMARSHAL* * *glib-mkenums* and set *GLIB_MKENUMS* * *glib-compile-schemas* and set *GLIB_COMPILE_SCHEMAS* (not mandatory) And set the variable *GSETTINGSSCHEMADIR* """ conf.find_program('glib-genmarshal', var='GLIB_GENMARSHAL') conf.find_perl_program('glib-mkenums', var='GLIB_MKENUMS') # when cross-compiling, gsettings.m4 locates the program with the following: # pkg-config --variable glib_compile_schemas gio-2.0 conf.find_program('glib-compile-schemas', var='GLIB_COMPILE_SCHEMAS', mandatory=False) def getstr(varname): return getattr(Options.options, varname, getattr(conf.env,varname, '')) # TODO make this dependent on the gnu_dirs tool? gsettingsschemadir = getstr('GSETTINGSSCHEMADIR') if not gsettingsschemadir: datadir = getstr('DATADIR') if not datadir: prefix = conf.env['PREFIX'] datadir = os.path.join(prefix, 'share') gsettingsschemadir = os.path.join(datadir, 'glib-2.0', 'schemas') conf.env['GSETTINGSSCHEMADIR'] = gsettingsschemadir def options(opt): """ Add the ``--gsettingsschemadir`` command-line option """ opt.add_option('--gsettingsschemadir', help='GSettings schema location [Default: ${datadir}/glib-2.0/schemas]',default='',dest='GSETTINGSSCHEMADIR') debian/waf-1.6/waflib/Tools/icc.py0000664000000000000000000000167312145744415013741 0ustar #!/usr/bin/env python # encoding: utf-8 # Stian Selnes, 2008 # Thomas Nagy 2009-2010 (ita) """ Detect the Intel C compiler """ import os, sys from waflib.Tools import ccroot, ar, gcc from waflib.Configure import conf @conf def find_icc(conf): """ Find the program icc and execute it to ensure it really is icc """ if sys.platform == 'cygwin': conf.fatal('The Intel compiler does not work on Cygwin') v = conf.env cc = None if v['CC']: cc = v['CC'] elif 'CC' in conf.environ: cc = conf.environ['CC'] if not cc: cc = conf.find_program('icc', var='CC') if not cc: cc = conf.find_program('ICL', var='CC') if not cc: conf.fatal('Intel C Compiler (icc) was not found') cc = conf.cmd_to_list(cc) conf.get_cc_version(cc, icc=True) v['CC'] = cc v['CC_NAME'] = 'icc' def configure(conf): conf.find_icc() conf.find_ar() conf.gcc_common_flags() conf.gcc_modifier_platform() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/Tools/gas.py0000664000000000000000000000062312145744415013747 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) "Detect as/gas/gcc for compiling assembly files" import waflib.Tools.asm # - leave this from waflib.Tools import ar def configure(conf): """ Find the programs gas/as/gcc and set the variable *AS* """ conf.find_program(['gas', 'as', 'gcc'], var='AS') conf.env.AS_TGT_F = ['-o'] conf.env.ASLNK_TGT_F = ['-o'] conf.find_ar() debian/waf-1.6/waflib/Tools/ccroot.py0000664000000000000000000004637012145744415014477 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Classes and methods shared by tools providing support for C-like language such as C/C++/D/Assembly/Go (this support module is almost never used alone). """ import os, sys, re from waflib import TaskGen, Task, Utils, Logs, Build, Options, Node, Errors from waflib.Logs import error, debug, warn from waflib.TaskGen import after_method, before_method, feature, taskgen_method, extension from waflib.Tools import c_aliases, c_preproc, c_config, c_osx, c_tests from waflib.Configure import conf USELIB_VARS = Utils.defaultdict(set) """ Mapping for features to :py:class:`waflib.ConfigSet.ConfigSet` variables. See :py:func:`waflib.Tools.ccroot.propagate_uselib_vars`. """ USELIB_VARS['c'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CCDEPS', 'CFLAGS', 'ARCH']) USELIB_VARS['cxx'] = set(['INCLUDES', 'FRAMEWORKPATH', 'DEFINES', 'CPPFLAGS', 'CXXDEPS', 'CXXFLAGS', 'ARCH']) USELIB_VARS['d'] = set(['INCLUDES', 'DFLAGS']) USELIB_VARS['cprogram'] = USELIB_VARS['cxxprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cshlib'] = USELIB_VARS['cxxshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'FRAMEWORK', 'FRAMEWORKPATH', 'ARCH']) USELIB_VARS['cstlib'] = USELIB_VARS['cxxstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['dprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) USELIB_VARS['dstlib'] = set(['ARFLAGS', 'LINKDEPS']) USELIB_VARS['go'] = set(['GOCFLAGS']) USELIB_VARS['goprogram'] = set(['GOLFLAGS']) USELIB_VARS['asm'] = set(['ASFLAGS']) # ================================================================================================= @taskgen_method def create_compiled_task(self, name, node): """ Create the compilation task: c, cxx, asm, etc. The output node is created automatically (object file with a typical **.o** extension). The task is appended to the list *compiled_tasks* which is then used by :py:func:`waflib.Tools.ccroot.apply_link` :param name: name of the task class :type name: string :param node: the file to compile :type node: :py:class:`waflib.Node.Node` :return: The task created :rtype: :py:class:`waflib.Task.Task` """ out = '%s.%d.o' % (node.name, self.idx) task = self.create_task(name, node, node.parent.find_or_declare(out)) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] return task @taskgen_method def to_incnodes(self, inlst): """ Task generator method provided to convert a list of string/nodes into a list of includes folders. The paths are assumed to be relative to the task generator path, except if they begin by **#** in which case they are searched from the top-level directory (``bld.srcnode``). The folders are simply assumed to be existing. The node objects in the list are returned in the output list. The strings are converted into node objects if possible. The node is searched from the source directory, and if a match is found, the equivalent build directory is created and added to the returned list too. When a folder cannot be found, it is ignored. :param inlst: list of folders :type inlst: space-delimited string or a list of string/nodes :rtype: list of :py:class:`waflib.Node.Node` :return: list of include folders as nodes """ lst = [] seen = set([]) for x in self.to_list(inlst): if x in seen or not x: continue seen.add(x) if isinstance(x, Node.Node): lst.append(x) else: if os.path.isabs(x): lst.append(self.bld.root.make_node(x) or x) else: if x[0] == '#': p = self.bld.bldnode.make_node(x[1:]) v = self.bld.srcnode.make_node(x[1:]) else: p = self.path.get_bld().make_node(x) v = self.path.make_node(x) if p.is_child_of(self.bld.bldnode): p.mkdir() lst.append(p) lst.append(v) return lst @feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): """ Task generator method that processes the attribute *includes*:: tg = bld(features='includes', includes='.') The folders only need to be relative to the current directory, the equivalent build directory is added automatically (for headers created in the build directory). This enable using a build directory or not (``top == out``). This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, and the list of include paths in ``tg.env.INCLUDES``. """ lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) self.includes_nodes = lst self.env['INCPATHS'] = [x.abspath() for x in lst] class link_task(Task.Task): """ Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`. .. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib """ color = 'YELLOW' inst_to = None """Default installation path for the link task outputs, or None to disable""" chmod = Utils.O644 """Default installation mode for the link task outputs""" def add_target(self, target): """ Process the *target* attribute to add the platform-specific prefix/suffix such as *.so* or *.exe*. The settings are retrieved from ``env.clsname_PATTERN`` """ if isinstance(target, str): pattern = self.env[self.__class__.__name__ + '_PATTERN'] if not pattern: pattern = '%s' folder, name = os.path.split(target) if self.__class__.__name__.find('shlib') > 0: if self.env.DEST_BINFMT == 'pe' and getattr(self.generator, 'vnum', None): # include the version in the dll file name, # the import lib file name stays unversionned. name = name + '-' + self.generator.vnum.split('.')[0] tmp = folder + os.sep + pattern % name target = self.generator.path.find_or_declare(tmp) self.set_outputs(target) class stlink_task(link_task): """ Base for static link tasks, which use *ar* most of the time. The target is always removed before being written. """ run_str = '${AR} ${ARFLAGS} ${AR_TGT_F}${TGT} ${AR_SRC_F}${SRC}' def rm_tgt(cls): old = cls.run def wrap(self): try: os.remove(self.outputs[0].abspath()) except OSError: pass return old(self) setattr(cls, 'run', wrap) rm_tgt(stlink_task) @feature('c', 'cxx', 'd', 'go', 'fc', 'asm') @after_method('process_source') def apply_link(self): """ Collect the tasks stored in ``compiled_tasks`` (created by :py:func:`waflib.Tools.ccroot.create_compiled_task`), and use the outputs for a new instance of :py:class:`waflib.Tools.ccroot.link_task`. The class to use is the first link task matching a name from the attribute *features*, for example:: def build(bld): tg = bld(features='cxx cxxprogram cprogram', source='main.c', target='app') will create the task ``tg.link_task`` as a new instance of :py:class:`waflib.Tools.cxx.cxxprogram` """ for x in self.features: if x == 'cprogram' and 'cxx' in self.features: # limited compat x = 'cxxprogram' elif x == 'cshlib' and 'cxx' in self.features: x = 'cxxshlib' if x in Task.classes: if issubclass(Task.classes[x], link_task): link = x break else: return objs = [t.outputs[0] for t in getattr(self, 'compiled_tasks', [])] self.link_task = self.create_task(link, objs) self.link_task.add_target(self.target) # remember that the install paths are given by the task generators # we need to define install_task even during the build phase because others might need the installation path try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.__class__.inst_to if inst_to: # install a copy of the node list we have at this moment (implib not added) self.install_task = self.bld.install_files(inst_to, self.link_task.outputs[:], env=self.env, chmod=self.link_task.chmod) @taskgen_method def use_rec(self, name, **kw): """ Processes the ``use`` keyword recursively. This method is kind of private and only meant to be used from ``process_use`` """ if name in self.tmp_use_not or name in self.tmp_use_seen: return try: y = self.bld.get_tgen_by_name(name) except Errors.WafError: self.uselib.append(name) self.tmp_use_not.add(name) return self.tmp_use_seen.append(name) y.post() # bind temporary attributes on the task generator y.tmp_use_objects = objects = kw.get('objects', True) y.tmp_use_stlib = stlib = kw.get('stlib', True) try: link_task = y.link_task except AttributeError: y.tmp_use_var = '' else: objects = False if not isinstance(y.link_task, stlink_task): stlib = False y.tmp_use_var = 'LIB' else: y.tmp_use_var = 'STLIB' p = self.tmp_use_prec for x in self.to_list(getattr(y, 'use', [])): try: p[x].append(name) except: p[x] = [name] self.use_rec(x, objects=objects, stlib=stlib) @feature('c', 'cxx', 'd', 'use', 'fc') @before_method('apply_incpaths', 'propagate_uselib_vars') @after_method('apply_link', 'process_source') def process_use(self): """ Process the ``use`` attribute which contains a list of task generator names:: def build(bld): bld.shlib(source='a.c', target='lib1') bld.program(source='main.c', target='app', use='lib1') See :py:func:`waflib.Tools.ccroot.use_rec`. """ use_not = self.tmp_use_not = set([]) use_seen = self.tmp_use_seen = [] # we would like an ordered set use_prec = self.tmp_use_prec = {} self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'use', [])) for x in names: self.use_rec(x) for x in use_not: if x in use_prec: del use_prec[x] # topological sort out = [] tmp = [] for x in self.tmp_use_seen: for k in use_prec.values(): if x in k: break else: tmp.append(x) while tmp: e = tmp.pop() out.append(e) try: nlst = use_prec[e] except KeyError: pass else: del use_prec[e] for x in nlst: for y in use_prec: if x in use_prec[y]: break else: tmp.append(x) if use_prec: raise Errors.WafError('Cycle detected in the use processing %r' % use_prec) out.reverse() link_task = getattr(self, 'link_task', None) for x in out: y = self.bld.get_tgen_by_name(x) var = y.tmp_use_var if var and link_task: if var == 'LIB' or y.tmp_use_stlib: self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) self.link_task.dep_nodes.extend(y.link_task.outputs) tmp_path = y.link_task.outputs[0].parent.path_from(self.bld.bldnode) self.env.append_value(var + 'PATH', [tmp_path]) else: if y.tmp_use_objects: self.add_objects_from_tgen(y) if getattr(y, 'export_includes', None): self.includes.extend(y.to_incnodes(y.export_includes)) # and finally, add the uselib variables (no recursion needed) for x in names: try: y = self.bld.get_tgen_by_name(x) except: if not self.env['STLIB_' + x] and not x in self.uselib: self.uselib.append(x) else: for k in self.to_list(getattr(y, 'uselib', [])): if not self.env['STLIB_' + k] and not k in self.uselib: self.uselib.append(k) @taskgen_method def add_objects_from_tgen(self, tg): # Not public yet, wait for waf 1.6.7 at least - the purpose of this is to add pdb files to the compiled # tasks but not to the link tasks (to avoid errors) try: link_task = self.link_task except AttributeError: pass else: for tsk in getattr(tg, 'compiled_tasks', []): for x in tsk.outputs: if x.name.endswith('.o') or x.name.endswith('.obj'): link_task.inputs.append(x) @taskgen_method def get_uselib_vars(self): """ :return: the *uselib* variables associated to the *features* attribute (see :py:attr:`waflib.Tools.ccroot.USELIB_VARS`) :rtype: list of string """ _vars = set([]) for x in self.features: if x in USELIB_VARS: _vars |= USELIB_VARS[x] return _vars @feature('c', 'cxx', 'd', 'fc', 'javac', 'cs', 'uselib') @after_method('process_use') def propagate_uselib_vars(self): """ Process uselib variables for adding flags. For example, the following target:: def build(bld): bld.env.AFLAGS_aaa = ['bar'] from waflib.Tools.ccroot import USELIB_VARS USELIB_VARS['aaa'] = set('AFLAGS') tg = bld(features='aaa', aflags='test') The *aflags* attribute will be processed and this method will set:: tg.env.AFLAGS = ['bar', 'test'] """ _vars = self.get_uselib_vars() env = self.env for x in _vars: y = x.lower() env.append_unique(x, self.to_list(getattr(self, y, []))) for x in self.features: for var in _vars: compvar = '%s_%s' % (var, x) env.append_value(var, env[compvar]) for x in self.to_list(getattr(self, 'uselib', [])): for v in _vars: env.append_value(v, env[v + '_' + x]) # ============ the code above must not know anything about import libs ========== @feature('cshlib', 'cxxshlib', 'fcshlib') @after_method('apply_link') def apply_implib(self): """ Handle dlls and their import libs on Windows-like systems. A ``.dll.a`` file called *import library* is generated. It must be installed as it is required for linking the library. """ if not self.env.DEST_BINFMT == 'pe': return dll = self.link_task.outputs[0] if isinstance(self.target, Node.Node): name = self.target.name else: name = os.path.split(self.target)[1] implib = self.env['implib_PATTERN'] % name implib = dll.parent.find_or_declare(implib) self.env.append_value('LINKFLAGS', self.env['IMPLIB_ST'] % implib.bldpath()) self.link_task.outputs.append(implib) if getattr(self, 'defs', None) and self.env.DEST_BINFMT == 'pe': node = self.path.find_resource(self.defs) if not node: raise Errors.WafError('invalid def file %r' % self.defs) if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): self.env.append_value('LINKFLAGS', '/def:%s' % node.path_from(self.bld.bldnode)) self.link_task.dep_nodes.append(node) else: #gcc for windows takes *.def file a an input without any special flag self.link_task.inputs.append(node) try: inst_to = self.install_path except AttributeError: inst_to = self.link_task.__class__.inst_to if not inst_to: return self.implib_install_task = self.bld.install_as('${PREFIX}/lib/%s' % implib.name, implib, self.env) # ============ the code above must not know anything about vnum processing on unix platforms ========= @feature('cshlib', 'cxxshlib', 'dshlib', 'fcshlib', 'vnum') @after_method('apply_link') def apply_vnum(self): """ Enforce version numbering on shared libraries. The valid version numbers must have at most two dots:: def build(bld): bld.shlib(source='a.c', target='foo', vnum='14.15.16') In this example, ``libfoo.so`` is installed as ``libfoo.so.1.2.3``, and the following symbolic links are created: * ``libfoo.so → libfoo.so.1.2.3`` * ``libfoo.so.1 → libfoo.so.1.2.3`` """ if not getattr(self, 'vnum', '') or os.name != 'posix' or self.env.DEST_BINFMT not in ('elf', 'mac-o'): return link = self.link_task nums = self.vnum.split('.') node = link.outputs[0] libname = node.name if libname.endswith('.dylib'): name3 = libname.replace('.dylib', '.%s.dylib' % self.vnum) name2 = libname.replace('.dylib', '.%s.dylib' % nums[0]) else: name3 = libname + '.' + self.vnum name2 = libname + '.' + nums[0] # add the so name for the ld linker - to disable, just unset env.SONAME_ST if self.env.SONAME_ST: v = self.env.SONAME_ST % name2 self.env.append_value('LINKFLAGS', v.split()) # the following task is just to enable execution from the build dir :-/ tsk = self.create_task('vnum', node, [node.parent.find_or_declare(name2), node.parent.find_or_declare(name3)]) if getattr(self.bld, 'is_install', None): self.install_task.hasrun = Task.SKIP_ME bld = self.bld path = self.install_task.dest t1 = bld.install_as(path + os.sep + name3, node, env=self.env, chmod=self.link_task.chmod) t2 = bld.symlink_as(path + os.sep + name2, name3) t3 = bld.symlink_as(path + os.sep + libname, name3) self.vnum_install_task = (t1, t2, t3) if '-dynamiclib' in self.env['LINKFLAGS'] and getattr(self, 'install_task', None): path = os.path.join(self.install_task.get_install_path(), self.link_task.outputs[0].name) self.env.append_value('LINKFLAGS', ['-install_name', path]) class vnum(Task.Task): """ Create the symbolic links for a versioned shared library. Instances are created by :py:func:`waflib.Tools.ccroot.apply_vnum` """ color = 'CYAN' quient = True ext_in = ['.bin'] def run(self): for x in self.outputs: path = x.abspath() try: os.remove(path) except OSError: pass try: os.symlink(self.inputs[0].name, path) except OSError: return 1 class fake_shlib(link_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME class fake_stlib(stlink_task): """ Task used for reading a system library and adding the dependency on it """ def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for x in self.outputs: x.sig = Utils.h_file(x.abspath()) return Task.SKIP_ME @conf def read_shlib(self, name, paths=[]): """ Read a system shared library, enabling its use as a local library. Will trigger a rebuild if the file changes:: def build(bld): bld.read_shlib('m') bld.program(source='main.c', use='m') """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='shlib') @conf def read_stlib(self, name, paths=[]): """ Read a system static library, enabling a use as a local library. Will trigger a rebuild if the file changes. """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='stlib') lib_patterns = { 'shlib' : ['lib%s.so', '%s.so', 'lib%s.dll', '%s.dll'], 'stlib' : ['lib%s.a', '%s.a', 'lib%s.dll', '%s.dll', 'lib%s.lib', '%s.lib'], } @feature('fake_lib') def process_lib(self): """ Find the location of a foreign library. Used by :py:class:`waflib.Tools.ccroot.read_shlib` and :py:class:`waflib.Tools.ccroot.read_stlib`. """ node = None names = [x % self.name for x in lib_patterns[self.lib_type]] for x in self.lib_paths + [self.path, '/usr/lib64', '/usr/lib', '/usr/local/lib64', '/usr/local/lib']: if not isinstance(x, Node.Node): x = self.bld.root.find_node(x) or self.path.find_node(x) if not x: continue for y in names: node = x.find_node(y) if node: node.sig = Utils.h_file(node.abspath()) break else: continue break else: raise Errors.WafError('could not find library %r' % self.name) self.link_task = self.create_task('fake_%s' % self.lib_type, [], [node]) self.target = self.name class fake_o(Task.Task): def runnable_status(self): return Task.SKIP_ME @extension('.o', '.obj') def add_those_o_files(self, node): tsk = self.create_task('fake_o', [], node) try: self.compiled_tasks.append(tsk) except AttributeError: self.compiled_tasks = [tsk] debian/waf-1.6/waflib/Tools/intltool.py0000664000000000000000000001240512145744415015042 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for translation tools such as msgfmt and intltool Usage:: def configure(conf): conf.load('gnu_dirs intltool') def build(bld): # process the .po files into .gmo files, and install them in LOCALEDIR bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") # process an input file, substituting the translations from the po dir bld( features = "intltool_in", podir = "../po", flags = ["-d", "-q", "-u", "-c"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. """ import os, re from waflib import Configure, TaskGen, Task, Utils, Runner, Options, Build, Logs import waflib.Tools.ccroot from waflib.TaskGen import feature, before_method from waflib.Logs import error @before_method('process_source') @feature('intltool_in') def apply_intltool_in_f(self): """ Create tasks to translate files by intltool-merge:: def build(bld): bld( features = "intltool_in", podir = "../po", flags = ["-d", "-q", "-u", "-c"], source = 'kupfer.desktop.in', install_path = "${DATADIR}/applications", ) :param podir: location of the .po files :type podir: string :param source: source files to process :type source: list of string :param flags: compilation flags ("-quc" by default) :type flags: list of string :param install_path: installation path :type install_path: string """ try: self.meths.remove('process_source') except ValueError: pass if not self.env.LOCALEDIR: self.env.LOCALEDIR = self.env.PREFIX + '/share/locale' for i in self.to_list(self.source): node = self.path.find_resource(i) podir = getattr(self, 'podir', 'po') podirnode = self.path.find_dir(podir) if not podirnode: error("could not find the podir %r" % podir) continue cache = getattr(self, 'intlcache', '.intlcache') self.env['INTLCACHE'] = os.path.join(self.path.bldpath(), podir, cache) self.env['INTLPODIR'] = podirnode.bldpath() self.env['INTLFLAGS'] = getattr(self, 'flags', ['-q', '-u', '-c']) task = self.create_task('intltool', node, node.change_ext('')) inst = getattr(self, 'install_path', '${LOCALEDIR}') if inst: self.bld.install_files(inst, task.outputs) @feature('intltool_po') def apply_intltool_po(self): """ Create tasks to process po files:: def build(bld): bld(features='intltool_po', appname='myapp', podir='po', install_path="${LOCALEDIR}") The relevant task generator arguments are: :param podir: directory of the .po files :type podir: string :param appname: name of the application :type appname: string :param install_path: installation directory :type install_path: string The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. """ try: self.meths.remove('process_source') except ValueError: pass if not self.env.LOCALEDIR: self.env.LOCALEDIR = self.env.PREFIX + '/share/locale' appname = getattr(self, 'appname', 'set_your_app_name') podir = getattr(self, 'podir', '') inst = getattr(self, 'install_path', '${LOCALEDIR}') linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) if linguas: # scan LINGUAS file for locales to process file = open(linguas.abspath()) langs = [] for line in file.readlines(): # ignore lines containing comments if not line.startswith('#'): langs += line.split() file.close() re_linguas = re.compile('[-a-zA-Z_@.]+') for lang in langs: # Make sure that we only process lines which contain locales if re_linguas.match(lang): node = self.path.find_resource(os.path.join(podir, re_linguas.match(lang).group() + '.po')) task = self.create_task('po', node, node.change_ext('.mo')) if inst: filename = task.outputs[0].name (langname, ext) = os.path.splitext(filename) inst_file = inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + appname + '.mo' self.bld.install_as(inst_file, task.outputs[0], chmod=getattr(self, 'chmod', Utils.O644), env=task.env) else: Logs.pprint('RED', "Error no LINGUAS file found in po directory") class po(Task.Task): """ Compile .po files into .gmo files """ run_str = '${MSGFMT} -o ${TGT} ${SRC}' color = 'BLUE' class intltool(Task.Task): """ Let intltool-merge translate an input file """ run_str = '${INTLTOOL} ${INTLFLAGS} ${INTLCACHE} ${INTLPODIR} ${SRC} ${TGT}' color = 'BLUE' def configure(conf): """ Detect the program *msgfmt* and set *conf.env.MSGFMT*. Detect the program *intltool-merge* and set *conf.env.INTLTOOL*. It is possible to set INTLTOOL in the environment, but it must not have spaces in it:: $ INTLTOOL="/path/to/the program/intltool" waf configure If a C/C++ compiler is present, execute a compilation test to find the header *locale.h*. """ conf.find_program('msgfmt', var='MSGFMT') conf.find_perl_program('intltool-merge', var='INTLTOOL') prefix = conf.env.PREFIX datadir = conf.env.DATADIR if not datadir: datadir = os.path.join(prefix,'share') conf.define('LOCALEDIR', os.path.join(datadir, 'locale').replace('\\', '\\\\')) conf.define('DATADIR', datadir.replace('\\', '\\\\')) if conf.env.CC or conf.env.CXX: conf.check(header_name='locale.h') debian/waf-1.6/waflib/Tools/gfortran.py0000664000000000000000000000437512145744415015027 0ustar #! /usr/bin/env python # encoding: utf-8 # DC 2008 # Thomas Nagy 2010 (ita) import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf @conf def find_gfortran(conf): """Find the gfortran program (will look in the environment variable 'FC')""" fc = conf.find_program(['gfortran','g77'], var='FC') # (fallback to g77 for systems, where no gfortran is available) fc = conf.cmd_to_list(fc) conf.get_gfortran_version(fc) conf.env.FC_NAME = 'GFORTRAN' @conf def gfortran_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-fPIC'] v['FORTRANMODFLAG'] = ['-J', ''] # template for module path v['FCFLAGS_DEBUG'] = ['-Werror'] # why not @conf def gfortran_modifier_win32(conf): fc_config.fortran_modifier_win32(conf) @conf def gfortran_modifier_cygwin(conf): fc_config.fortran_modifier_cygwin(conf) @conf def gfortran_modifier_darwin(conf): fc_config.fortran_modifier_darwin(conf) @conf def gfortran_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() gfortran_modifier_func = getattr(conf, 'gfortran_modifier_' + dest_os, None) if gfortran_modifier_func: gfortran_modifier_func() @conf def get_gfortran_version(conf, fc): """Get the compiler version""" # ensure this is actually gfortran, not an imposter. version_re = re.compile(r"GNU\s*Fortran", re.I).search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the compiler type') # --- now get more detailed info -- see c_config.get_cc_version cmd = fc + ['-dM', '-E', '-'] out, err = fc_config.getoutput(conf, cmd, stdin=True) if out.find('__GNUC__') < 0: conf.fatal('Could not determine the compiler type') k = {} out = out.split('\n') import shlex for line in out: lst = shlex.split(line) if len(lst)>2: key = lst[1] val = lst[2] k[key] = val def isD(var): return var in k def isT(var): return var in k and k[var] != '0' conf.env['FC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) def configure(conf): conf.find_gfortran() conf.find_ar() conf.fc_flags() conf.gfortran_flags() conf.gfortran_modifier_platform() debian/waf-1.6/waflib/Tools/d_config.py0000664000000000000000000000234712145744415014752 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) from waflib import Utils from waflib.Configure import conf @conf def d_platform_flags(self): """ Set the extensions dll/so for d programs and libraries """ v = self.env if not v.DEST_OS: v.DEST_OS = Utils.unversioned_sys_platform() if Utils.destos_to_binfmt(self.env.DEST_OS) == 'pe': v['dprogram_PATTERN'] = '%s.exe' v['dshlib_PATTERN'] = 'lib%s.dll' v['dstlib_PATTERN'] = 'lib%s.a' else: v['dprogram_PATTERN'] = '%s' v['dshlib_PATTERN'] = 'lib%s.so' v['dstlib_PATTERN'] = 'lib%s.a' DLIB = ''' version(D_Version2) { import std.stdio; int main() { writefln("phobos2"); return 0; } } else { version(Tango) { import tango.stdc.stdio; int main() { printf("tango"); return 0; } } else { import std.stdio; int main() { writefln("phobos1"); return 0; } } } ''' """Detection string for the D standard library""" @conf def check_dlibrary(self): """ Detect the kind of standard library that comes with the compiler, will set conf.env.DLIBRARY to tango, phobos1 or phobos2. """ ret = self.check_cc(features='d dprogram', fragment=DLIB, compile_filename='test.d', execute=True, define_ret=True) self.env.DLIBRARY = ret.strip() debian/waf-1.6/waflib/Tools/kde4.py0000664000000000000000000000516112145744415014026 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Support for the KDE4 libraries and msgfmt """ import os, sys, re from waflib import Options, TaskGen, Task, Utils from waflib.TaskGen import feature, after_method @feature('msgfmt') def apply_msgfmt(self): """ Process all languages to create .mo files and to install them:: def build(bld): bld(features='msgfmt', langs='es de fr', appname='myapp', install_path='${KDE4_LOCALE_INSTALL_DIR}') """ for lang in self.to_list(self.langs): node = self.path.find_resource(lang+'.po') task = self.create_task('msgfmt', node, node.change_ext('.mo')) langname = lang.split('/') langname = langname[-1] inst = getattr(self, 'install_path', '${KDE4_LOCALE_INSTALL_DIR}') self.bld.install_as( inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + getattr(self, 'appname', 'set_your_appname') + '.mo', task.outputs[0], chmod = getattr(self, 'chmod', Utils.O644)) class msgfmt(Task.Task): """ Transform .po files into .mo files """ color = 'BLUE' run_str = '${MSGFMT} ${SRC} -o ${TGT}' def configure(self): """ Detect kde4-config and set various variables for the *use* system:: def options(opt): opt.load('compiler_cxx kde4') def configure(conf): conf.load('compiler_cxx kde4') def build(bld): bld.program(source='main.c', target='app', use='KDECORE KIO KHTML') """ kdeconfig = self.find_program('kde4-config') prefix = self.cmd_and_log('%s --prefix' % kdeconfig).strip() fname = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(fname) except OSError: fname = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix try: os.stat(fname) except OSError: self.fatal('could not open %s' % fname) try: txt = Utils.readf(fname) except (OSError, IOError): self.fatal('could not read %s' % fname) txt = txt.replace('\\\n', '\n') fu = re.compile('#(.*)\n') txt = fu.sub('', txt) setregexp = re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') found = setregexp.findall(txt) for (_, key, val) in found: #print key, val self.env[key] = val # well well, i could just write an interpreter for cmake files self.env['LIB_KDECORE']= ['kdecore'] self.env['LIB_KDEUI'] = ['kdeui'] self.env['LIB_KIO'] = ['kio'] self.env['LIB_KHTML'] = ['khtml'] self.env['LIB_KPARTS'] = ['kparts'] self.env['LIBPATH_KDECORE'] = [self.env['KDE4_LIB_INSTALL_DIR']] self.env['INCLUDES_KDECORE'] = [self.env['KDE4_INCLUDE_INSTALL_DIR']] self.env.append_value('INCLUDES_KDECORE', [self.env['KDE4_INCLUDE_INSTALL_DIR']+ os.sep + 'KDE']) self.find_program('msgfmt', var='MSGFMT') debian/waf-1.6/waflib/Tools/c_config.py0000664000000000000000000010345612145744415014754 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ C/C++/D configuration helpers """ import os, imp, sys, re, shlex, shutil from waflib import Build, Utils, Configure, Task, Options, Logs, TaskGen, Errors, ConfigSet, Runner from waflib.TaskGen import before_method, after_method, feature from waflib.Configure import conf WAF_CONFIG_H = 'config.h' """default name for the config.h file""" DEFKEYS = 'define_key' INCKEYS = 'include_key' cfg_ver = { 'atleast-version': '>=', 'exact-version': '==', 'max-version': '<=', } SNIP_FUNCTION = ''' int main() { void *p; p=(void*)(%s); return 0; } ''' """Code template for checking for functions""" SNIP_TYPE = ''' int main() { if ((%(type_name)s *) 0) return 0; if (sizeof (%(type_name)s)) return 0; } ''' """Code template for checking for types""" SNIP_CLASS = ''' int main() { if ( } ''' SNIP_EMPTY_PROGRAM = ''' int main() { return 0; } ''' SNIP_FIELD = ''' int main() { char *off; off = (char*) &((%(type_name)s*)0)->%(field_name)s; return (size_t) off < sizeof(%(type_name)s); } ''' MACRO_TO_DESTOS = { '__linux__' : 'linux', '__GNU__' : 'gnu', # hurd '__FreeBSD__' : 'freebsd', '__NetBSD__' : 'netbsd', '__OpenBSD__' : 'openbsd', '__sun' : 'sunos', '__hpux' : 'hpux', '__sgi' : 'irix', '_AIX' : 'aix', '__CYGWIN__' : 'cygwin', '__MSYS__' : 'msys', '_UWIN' : 'uwin', '_WIN64' : 'win32', '_WIN32' : 'win32', # Note about darwin: this is also tested with 'defined __APPLE__ && defined __MACH__' somewhere below in this file. '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' : 'darwin', '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' : 'darwin', # iphone '__QNX__' : 'qnx', '__native_client__' : 'nacl' # google native client platform } MACRO_TO_DEST_CPU = { '__x86_64__' : 'x86_64', '__i386__' : 'x86', '__ia64__' : 'ia', '__mips__' : 'mips', '__sparc__' : 'sparc', '__alpha__' : 'alpha', '__arm__' : 'arm', '__hppa__' : 'hppa', '__powerpc__' : 'powerpc', } @conf def parse_flags(self, line, uselib, env=None, force_static=False): """ Parse the flags from the input lines, and add them to the relevant use variables:: def configure(conf): conf.parse_flags('-O3', uselib_store='FOO') # conf.env.CXXFLAGS_FOO = ['-O3'] # conf.env.CFLAGS_FOO = ['-O3'] :param line: flags :type line: string :param uselib: where to add the flags :type uselib: string :param env: config set or conf.env by default :type env: :py:class:`waflib.ConfigSet.ConfigSet` """ assert(isinstance(line, str)) env = env or self.env # append_unique is not always possible # for example, apple flags may require both -arch i386 and -arch ppc app = env.append_value appu = env.append_unique #lst = shlex.split(line) # issue #811 lex = shlex.shlex(line, posix=False) lex.whitespace_split = True lex.commenters = '' lst = list(lex) while lst: x = lst.pop(0) st = x[:2] ot = x[2:] if st == '-I' or st == '/I': if not ot: ot = lst.pop(0) appu('INCLUDES_' + uselib, [ot]) elif st == '-include': tmp = [x, lst.pop(0)] app('CFLAGS', tmp) app('CXXFLAGS', tmp) elif st == '-D' or (self.env.CXX_NAME == 'msvc' and st == '/D'): # not perfect but.. if not ot: ot = lst.pop(0) app('DEFINES_' + uselib, [ot]) elif st == '-l': if not ot: ot = lst.pop(0) prefix = force_static and 'STLIB_' or 'LIB_' appu(prefix + uselib, [ot]) elif st == '-L': if not ot: ot = lst.pop(0) appu('LIBPATH_' + uselib, [ot]) elif x == '-pthread' or x.startswith('+') or x.startswith('-std'): app('CFLAGS_' + uselib, [x]) app('CXXFLAGS_' + uselib, [x]) app('LINKFLAGS_' + uselib, [x]) elif x == '-framework': appu('FRAMEWORK_' + uselib, [lst.pop(0)]) elif x.startswith('-F'): appu('FRAMEWORKPATH_' + uselib, [x[2:]]) elif x.startswith('-Wl'): app('LINKFLAGS_' + uselib, [x]) elif x.startswith('-m') or x.startswith('-f') or x.startswith('-dynamic'): app('CFLAGS_' + uselib, [x]) app('CXXFLAGS_' + uselib, [x]) elif x.startswith('-bundle'): app('LINKFLAGS_' + uselib, [x]) elif x.startswith('-undefined'): arg = lst.pop(0) app('LINKFLAGS_' + uselib, [x, arg]) elif x.startswith('-arch') or x.startswith('-isysroot'): tmp = [x, lst.pop(0)] app('CFLAGS_' + uselib, tmp) app('CXXFLAGS_' + uselib, tmp) app('LINKFLAGS_' + uselib, tmp) elif x.endswith('.a') or x.endswith('.so') or x.endswith('.dylib'): appu('LINKFLAGS_' + uselib, [x]) # not cool, #762 @conf def ret_msg(self, f, kw): if isinstance(f, str): return f return f(kw) @conf def validate_cfg(self, kw): """ Search for the program *pkg-config* if missing, and validate the parameters to pass to :py:func:`waflib.Tools.c_config.exec_cfg`. :param path: the **-config program to use** (default is *pkg-config*) :type path: list of string :param msg: message to display to describe the test executed :type msg: string :param okmsg: message to display when the test is successful :type okmsg: string :param errmsg: message to display in case of error :type errmsg: string """ if not 'path' in kw: if not self.env.PKGCONFIG: self.find_program('pkg-config', var='PKGCONFIG') kw['path'] = self.env.PKGCONFIG # pkg-config version if 'atleast_pkgconfig_version' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] return if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'errmsg' in kw: kw['errmsg'] = 'not found' if 'modversion' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %r version' % kw['modversion'] return # checking for the version of a module, for the moment, one thing at a time for x in cfg_ver.keys(): y = x.replace('-', '_') if y in kw: if not 'package' in kw: raise ValueError('%s requires a package' % x) if not 'msg' in kw: kw['msg'] = 'Checking for %r %s %s' % (kw['package'], cfg_ver[x], kw[y]) return if not 'msg' in kw: kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path']) @conf def exec_cfg(self, kw): """ Execute the program *pkg-config*: * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return * if modversion is given, then return the module version * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) :type atleast_pkgconfig_version: string :param package: package name, for example *gtk+-2.0* :type package: string :param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables. :type uselib_store: string :param modversion: if provided, return the version of the given module and define *name*\_VERSION :type modversion: string :param args: arguments to give to *package* when retrieving flags :type args: list of string :param variables: return the values of particular variables :type variables: list of string :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) :type define_variable: dict(string: string) """ # pkg-config version if 'atleast_pkgconfig_version' in kw: cmd = [kw['path'], '--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] self.cmd_and_log(cmd) if not 'okmsg' in kw: kw['okmsg'] = 'yes' return # checking for the version of a module for x in cfg_ver: y = x.replace('-', '_') if y in kw: self.cmd_and_log([kw['path'], '--%s=%s' % (x, kw[y]), kw['package']]) if not 'okmsg' in kw: kw['okmsg'] = 'yes' self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) break # retrieving the version of a module if 'modversion' in kw: version = self.cmd_and_log([kw['path'], '--modversion', kw['modversion']]).strip() self.define('%s_VERSION' % Utils.quote_define_name(kw.get('uselib_store', kw['modversion'])), version) return version lst = [kw['path']] defi = kw.get('define_variable', None) if not defi: defi = self.env.PKG_CONFIG_DEFINES or {} for key, val in defi.items(): lst.append('--define-variable=%s=%s' % (key, val)) if kw['package']: lst.extend(Utils.to_list(kw['package'])) # retrieving variables of a module if 'variables' in kw: env = kw.get('env', self.env) uselib = kw.get('uselib_store', kw['package'].upper()) vars = Utils.to_list(kw['variables']) for v in vars: val = self.cmd_and_log(lst + ['--variable=' + v]).strip() var = '%s_%s' % (uselib, v) env[var] = val if not 'okmsg' in kw: kw['okmsg'] = 'yes' return static = False if 'args' in kw: args = Utils.to_list(kw['args']) if '--static' in args or '--static-libs' in args: static = True lst += args # so we assume the command-line will output flags to be parsed afterwards ret = self.cmd_and_log(lst) if not 'okmsg' in kw: kw['okmsg'] = 'yes' self.define(self.have_define(kw.get('uselib_store', kw['package'])), 1, 0) self.parse_flags(ret, kw.get('uselib_store', kw['package'].upper()), kw.get('env', self.env), force_static=static) return ret @conf def check_cfg(self, *k, **kw): """ Check for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). Encapsulate the calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` A few examples:: def configure(conf): conf.load('compiler_c') conf.check_cfg(package='glib-2.0', args='--libs --cflags') conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0', args='--cflags --libs') conf.check_cfg(package='pango') conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) conf.check_cfg(package='pango', args=['pango >= 0.1.0', 'pango < 9.9.9', '--cflags', '--libs'], msg="Checking for 'pango 0.1.0'") conf.check_cfg(path='sdl-config', args='--cflags --libs', package='', uselib_store='SDL') conf.check_cfg(path='mpicc', args='--showme:compile --showme:link', package='', uselib_store='OPEN_MPI', mandatory=False) """ if k: lst = k[0].split() kw['package'] = lst[0] kw['args'] = ' '.join(lst[1:]) self.validate_cfg(kw) if 'msg' in kw: self.start_msg(kw['msg']) ret = None try: ret = self.exec_cfg(kw) except self.errors.WafError as e: if 'errmsg' in kw: self.end_msg(kw['errmsg'], 'YELLOW') if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret if 'okmsg' in kw: self.end_msg(self.ret_msg(kw['okmsg'], kw)) return ret @conf def validate_c(self, kw): """ pre-check the parameters that will be given to run_c_code :param env: an optional environment (modified -> provide a copy) :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param compiler: c or cxx (tries to guess what is best) :type compiler: string :param type: cprogram, cshlib, cstlib - not required if *features are given directly* :type type: binary to create :param feature: desired features for the task generator that will execute the test, for example ``cxx cxxstlib`` :type feature: list of string :param fragment: provide a piece of code for the test (default is to let the system create one) :type fragment: string :param uselib_store: define variables after the test is executed (IMPORTANT!) :type uselib_store: string :param use: parameters to use for building (just like the normal *use* keyword) :type use: list of string :param define_name: define to set when the check is over :type define_name: string :param execute: execute the resulting binary :type execute: bool :param define_ret: if execute is set to True, use the execution output in both the define and the return value :type define_ret: bool :param header_name: check for a particular header :type header_name: string :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers :type auto_add_header_name: bool """ if not 'env' in kw: kw['env'] = self.env.derive() env = kw['env'] if not 'compiler' in kw and not 'features' in kw: kw['compiler'] = 'c' if env['CXX_NAME'] and Task.classes.get('cxx', None): kw['compiler'] = 'cxx' if not self.env['CXX']: self.fatal('a c++ compiler is required') else: if not self.env['CC']: self.fatal('a c compiler is required') if not 'compile_mode' in kw: kw['compile_mode'] = 'c' if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx': kw['compile_mode'] = 'cxx' if not 'type' in kw: kw['type'] = 'cprogram' if not 'features' in kw: kw['features'] = [kw['compile_mode'], kw['type']] # "cprogram c" else: kw['features'] = Utils.to_list(kw['features']) if not 'compile_filename' in kw: kw['compile_filename'] = 'test.c' + ((kw['compile_mode'] == 'cxx') and 'pp' or '') def to_header(dct): if 'header_name' in dct: dct = Utils.to_list(dct['header_name']) return ''.join(['#include <%s>\n' % x for x in dct]) return '' #OSX if 'framework_name' in kw: fwkname = kw['framework_name'] if not 'uselib_store' in kw: kw['uselib_store'] = fwkname.upper() if not kw.get('no_header', False): if not 'header_name' in kw: kw['header_name'] = [] fwk = '%s/%s.h' % (fwkname, fwkname) if kw.get('remove_dot_h', None): fwk = fwk[:-2] kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk] kw['msg'] = 'Checking for framework %s' % fwkname kw['framework'] = fwkname #kw['frameworkpath'] = set it yourself if 'function_name' in kw: fu = kw['function_name'] if not 'msg' in kw: kw['msg'] = 'Checking for function %s' % fu kw['code'] = to_header(kw) + SNIP_FUNCTION % fu if not 'uselib_store' in kw: kw['uselib_store'] = fu.upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(fu) elif 'type_name' in kw: tu = kw['type_name'] if not 'header_name' in kw: kw['header_name'] = 'stdint.h' if 'field_name' in kw: field = kw['field_name'] kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field} if not 'msg' in kw: kw['msg'] = 'Checking for field %s in %s' % (field, tu) if not 'define_name' in kw: kw['define_name'] = self.have_define((tu + '_' + field).upper()) else: kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu} if not 'msg' in kw: kw['msg'] = 'Checking for type %s' % tu if not 'define_name' in kw: kw['define_name'] = self.have_define(tu.upper()) elif 'header_name' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for header %s' % kw['header_name'] l = Utils.to_list(kw['header_name']) assert len(l)>0, 'list of headers in header_name is empty' kw['code'] = to_header(kw) + SNIP_EMPTY_PROGRAM if not 'uselib_store' in kw: kw['uselib_store'] = l[0].upper() if not 'define_name' in kw: kw['define_name'] = self.have_define(l[0]) if 'lib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for library %s' % kw['lib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['lib'].upper() if 'stlib' in kw: if not 'msg' in kw: kw['msg'] = 'Checking for static library %s' % kw['stlib'] if not 'uselib_store' in kw: kw['uselib_store'] = kw['stlib'].upper() if 'fragment' in kw: # an additional code fragment may be provided to replace the predefined code # in custom headers kw['code'] = kw['fragment'] if not 'msg' in kw: kw['msg'] = 'Checking for code snippet' if not 'errmsg' in kw: kw['errmsg'] = 'no' for (flagsname,flagstype) in [('cxxflags','compiler'), ('cflags','compiler'), ('linkflags','linker')]: if flagsname in kw: if not 'msg' in kw: kw['msg'] = 'Checking for %s flags %s' % (flagstype, kw[flagsname]) if not 'errmsg' in kw: kw['errmsg'] = 'no' if not 'execute' in kw: kw['execute'] = False if kw['execute']: kw['features'].append('test_exec') if not 'errmsg' in kw: kw['errmsg'] = 'not found' if not 'okmsg' in kw: kw['okmsg'] = 'yes' if not 'code' in kw: kw['code'] = SNIP_EMPTY_PROGRAM # if there are headers to append automatically to the next tests if self.env[INCKEYS]: kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] if not kw.get('success'): kw['success'] = None if 'define_name' in kw: self.undefine(kw['define_name']) assert 'msg' in kw, 'invalid parameters, read http://freehackers.org/~tnagy/wafbook/single.html#config_helpers_c' @conf def post_check(self, *k, **kw): "Set the variables after a test executed in :py:func:`waflib.Tools.c_config.check` was run successfully" is_success = 0 if kw['execute']: if kw['success'] is not None: if kw.get('define_ret', False): is_success = kw['success'] else: is_success = (kw['success'] == 0) else: is_success = (kw['success'] == 0) if 'define_name' in kw: # TODO simplify? if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: nm = kw['define_name'] if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str): self.define(kw['define_name'], is_success, quote=kw.get('quote', 1)) else: self.define_cond(kw['define_name'], is_success) else: self.define_cond(kw['define_name'], is_success) if 'header_name' in kw: if kw.get('auto_add_header_name', False): self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) if is_success and 'uselib_store' in kw: from waflib.Tools import ccroot # TODO see get_uselib_vars from ccroot.py _vars = set([]) for x in kw['features']: if x in ccroot.USELIB_VARS: _vars |= ccroot.USELIB_VARS[x] for k in _vars: lk = k.lower() if k == 'INCLUDES': lk = 'includes' if k == 'DEFINES': lk = 'defines' if lk in kw: val = kw[lk] # remove trailing slash if isinstance(val, str): val = val.rstrip(os.path.sep) self.env.append_unique(k + '_' + kw['uselib_store'], val) return is_success @conf def check(self, *k, **kw): """ Perform a configuration test by calling :py:func:`waflib.Tools.c_config.run_c_code`. For the complete list of parameters, see :py:func:`waflib.Tools.c_config.validate_c`. To force a specific compiler, prefer the methods :py:func:`waflib.Tools.c_config.check_cxx` or :py:func:`waflib.Tools.c_config.check_cc` """ self.validate_c(kw) self.start_msg(kw['msg']) ret = None try: ret = self.run_c_code(*k, **kw) except self.errors.ConfigurationError as e: self.end_msg(kw['errmsg'], 'YELLOW') if Logs.verbose > 1: raise else: self.fatal('The configuration failed') else: kw['success'] = ret self.end_msg(self.ret_msg(kw['okmsg'], kw)) ret = self.post_check(*k, **kw) if not ret: self.fatal('The configuration failed %r' % ret) return ret class test_exec(Task.Task): """ A task for executing a programs after they are built. See :py:func:`waflib.Tools.c_config.test_exec_fun`. """ color = 'PINK' def run(self): if getattr(self.generator, 'rpath', None): if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) else: self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()]) else: env = self.env.env or {} env.update(dict(os.environ)) for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') if getattr(self.generator, 'define_ret', False): self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env) else: self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env) @feature('test_exec') @after_method('apply_link') def test_exec_fun(self): """ The feature **test_exec** is used to create a task that will to execute the binary created (link task output) during the build. The exit status will be set on the build context, so only one program may have the feature *test_exec*. This is used by configuration tests:: def configure(conf): conf.check(execute=True) """ self.create_task('test_exec', self.link_task.outputs[0]) CACHE_RESULTS = 1 COMPILE_ERRORS = 2 @conf def run_c_code(self, *k, **kw): """ Create a temporary build context to execute a build. A reference to that build context is kept on self.test_bld for debugging purposes, and you should not rely on it too much (read the note on the cache below). The parameters given in the arguments to this function are passed as arguments for a single task generator created in the build. Only three parameters are obligatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string :param code: code to write in the filename to compile :type code: string Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. This function also provides a limited cache. To use it, provide the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, action='count', help='Use a configuration cache') And execute the configuration with the following command-line:: $ waf configure --confcache """ lst = [str(v) for (p, v) in kw.items() if p != 'env'] h = Utils.h_list(lst) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) try: os.makedirs(dir) except: pass try: os.stat(dir) except: self.fatal('cannot use the configuration test folder %r' % dir) cachemode = getattr(Options.options, 'confcache', None) if cachemode == CACHE_RESULTS: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_c_code')) ret = proj['cache_run_c_code'] except: pass else: if isinstance(ret, str) and ret.startswith('Test does not build'): self.fatal(ret) return ret bdir = os.path.join(dir, 'testbuild') if not os.path.exists(bdir): os.makedirs(bdir) self.test_bld = bld = Build.BuildContext(top_dir=dir, out_dir=bdir) bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' if kw['compile_filename']: node = bld.srcnode.make_node(kw['compile_filename']) node.write(kw['code']) bld.logger = self.logger bld.all_envs.update(self.all_envs) # not really necessary bld.env = kw['env'] o = bld(features=kw['features'], source=kw['compile_filename'], target='testprog') for k, v in kw.items(): setattr(o, k, v) self.to_log("==>\n%s\n<==" % kw['code']) # compile the program bld.targets = '*' ret = -1 try: try: bld.compile() except Errors.WafError: ret = 'Test does not build: %s' % Utils.ex_stack() self.fatal(ret) else: ret = getattr(bld, 'retval', 0) finally: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_c_code'] = ret proj.store(os.path.join(dir, 'cache_run_c_code')) return ret @conf def check_cxx(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *c++* programming language """ kw['compiler'] = 'cxx' return self.check(*k, **kw) @conf def check_cc(self, *k, **kw): """ Same as :py:func:`waflib.Tools.c_config.check` but default to the *c* programming language """ kw['compiler'] = 'c' return self.check(*k, **kw) @conf def define(self, key, val, quote=True): """ Store a single define and its state into conf.env.DEFINES :param key: define name :type key: string :param val: value :type val: int or string :param quote: enclose strings in quotes (yes by default) :type quote: bool """ assert key and isinstance(key, str) if isinstance(val, int) or isinstance(val, float): s = '%s=%s' else: s = quote and '%s="%s"' or '%s=%s' app = s % (key, str(val)) ban = key + '=' lst = self.env['DEFINES'] for x in lst: if x.startswith(ban): lst[lst.index(x)] = app break else: self.env.append_value('DEFINES', app) self.env.append_unique(DEFKEYS, key) @conf def undefine(self, key): """ Remove a define from conf.env.DEFINES :param key: define name :type key: string """ assert key and isinstance(key, str) ban = key + '=' lst = [x for x in self.env['DEFINES'] if not x.startswith(ban)] self.env['DEFINES'] = lst self.env.append_unique(DEFKEYS, key) @conf def define_cond(self, key, val): """ Conditionally define a name:: def configure(conf): conf.define_cond('A', True) # equivalent to: # if val: conf.define('A', 1) # else: conf.undefine('A') :param key: define name :type key: string :param val: value :type val: int or string """ assert key and isinstance(key, str) if val: self.define(key, 1) else: self.undefine(key) @conf def is_defined(self, key): """ :param key: define name :type key: string :return: True if the define is set :rtype: bool """ assert key and isinstance(key, str) ban = key + '=' for x in self.env['DEFINES']: if x.startswith(ban): return True return False @conf def get_define(self, key): """ :param key: define name :type key: string :return: the value of a previously stored define or None if it is not set """ assert key and isinstance(key, str) ban = key + '=' for x in self.env['DEFINES']: if x.startswith(ban): return x[len(ban):] return None @conf def have_define(self, key): """ :param key: define name :type key: string :return: the input key prefixed by *HAVE_* and substitute any invalid characters. :rtype: string """ return self.__dict__.get('HAVE_PAT', 'HAVE_%s') % Utils.quote_define_name(key) @conf def write_config_header(self, configfile='', guard='', top=False, env=None, defines=True, headers=False, remove=True): """ Write a configuration header containing defines and includes:: def configure(cnf): cnf.define('A', 1) cnf.write_config_header('config.h') :param configfile: relative path to the file to create :type configfile: string :param env: config set to read the definitions from (default is conf.env) :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param top: write the configuration header from the build directory (default is from the current path) :type top: bool :param defines: add the defines (yes by default) :type defines: bool :param headers: add #include in the file :type headers: bool :param remove: remove the defines after they are added (yes by default) :type remove: bool """ if not configfile: configfile = WAF_CONFIG_H waf_guard = guard or '_%s_WAF' % Utils.quote_define_name(configfile) node = top and self.bldnode or self.path.get_bld() node = node.make_node(configfile) node.parent.mkdir() lst = ['/* WARNING! All changes made to this file will be lost! */\n'] lst.append('#ifndef %s\n#define %s\n' % (waf_guard, waf_guard)) lst.append(self.get_config_header(defines, headers)) lst.append('\n#endif /* %s */\n' % waf_guard) node.write('\n'.join(lst)) env = env or self.env # config files are not removed on "waf clean" env.append_unique(Build.CFG_FILES, [node.abspath()]) if remove: for key in self.env[DEFKEYS]: self.undefine(key) self.env[DEFKEYS] = [] @conf def get_config_header(self, defines=True, headers=False): """ Create the contents of a ``config.h`` file from the defines and includes set in conf.env.define_key / conf.env.include_key. No include guards are added. :param defines: write the defines values :type defines: bool :param headers: write the headers :type headers: bool :return: the contents of a ``config.h`` file :rtype: string """ lst = [] if headers: for x in self.env[INCKEYS]: lst.append('#include <%s>' % x) if defines: for x in self.env[DEFKEYS]: if self.is_defined(x): val = self.get_define(x) lst.append('#define %s %s' % (x, val)) else: lst.append('/* #undef %s */' % x) return "\n".join(lst) @conf def cc_add_flags(conf): """ Read the CFLAGS/CPPFLAGS from os.environ and add to conf.env.CFLAGS """ conf.add_os_flags('CPPFLAGS', 'CFLAGS') conf.add_os_flags('CFLAGS') @conf def cxx_add_flags(conf): """ Read the CXXFLAGS/CPPFLAGS and add to conf.env.CXXFLAGS """ conf.add_os_flags('CPPFLAGS', 'CXXFLAGS') conf.add_os_flags('CXXFLAGS') @conf def link_add_flags(conf): """ Read the LINKFLAGS/LDFLAGS and add to conf.env.LDFLAGS """ conf.add_os_flags('LINKFLAGS') conf.add_os_flags('LDFLAGS', 'LINKFLAGS') @conf def cc_load_tools(conf): """ Load the c tool """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('c') @conf def cxx_load_tools(conf): """ Load the cxx tool """ if not conf.env.DEST_OS: conf.env.DEST_OS = Utils.unversioned_sys_platform() conf.load('cxx') @conf def get_cc_version(conf, cc, gcc=False, icc=False): """ Run the preprocessor to determine the compiler version The variables CC_VERSION, DEST_OS, DEST_BINFMT and DEST_CPU will be set in *conf.env* """ cmd = cc + ['-dM', '-E', '-'] env = conf.env.env or None try: p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, stderr=Utils.subprocess.PIPE, env=env) p.stdin.write('\n'.encode()) out = p.communicate()[0] except: conf.fatal('Could not determine the compiler version %r' % cmd) if not isinstance(out, str): out = out.decode(sys.stdout.encoding) if gcc: if out.find('__INTEL_COMPILER') >= 0: conf.fatal('The intel compiler pretends to be gcc') if out.find('__GNUC__') < 0: conf.fatal('Could not determine the compiler type') if icc and out.find('__INTEL_COMPILER') < 0: conf.fatal('Not icc/icpc') k = {} if icc or gcc: out = out.split('\n') for line in out: lst = shlex.split(line) if len(lst)>2: key = lst[1] val = lst[2] k[key] = val def isD(var): return var in k def isT(var): return var in k and k[var] != '0' # Some documentation is available at http://predef.sourceforge.net # The names given to DEST_OS must match what Utils.unversioned_sys_platform() returns. if not conf.env.DEST_OS: conf.env.DEST_OS = '' for i in MACRO_TO_DESTOS: if isD(i): conf.env.DEST_OS = MACRO_TO_DESTOS[i] break else: if isD('__APPLE__') and isD('__MACH__'): conf.env.DEST_OS = 'darwin' elif isD('__unix__'): # unix must be tested last as it's a generic fallback conf.env.DEST_OS = 'generic' if isD('__ELF__'): conf.env.DEST_BINFMT = 'elf' elif isD('__WINNT__') or isD('__CYGWIN__'): conf.env.DEST_BINFMT = 'pe' conf.env.LIBDIR = conf.env['PREFIX'] + '/bin' elif isD('__APPLE__'): conf.env.DEST_BINFMT = 'mac-o' if not conf.env.DEST_BINFMT: # Infer the binary format from the os name. conf.env.DEST_BINFMT = Utils.destos_to_binfmt(conf.env.DEST_OS) for i in MACRO_TO_DEST_CPU: if isD(i): conf.env.DEST_CPU = MACRO_TO_DEST_CPU[i] break Logs.debug('ccroot: dest platform: ' + ' '.join([conf.env[x] or '?' for x in ('DEST_OS', 'DEST_BINFMT', 'DEST_CPU')])) if icc: ver = k['__INTEL_COMPILER'] conf.env['CC_VERSION'] = (ver[:-2], ver[-2], ver[-1]) else: conf.env['CC_VERSION'] = (k['__GNUC__'], k['__GNUC_MINOR__'], k['__GNUC_PATCHLEVEL__']) return k @conf def get_xlc_version(conf, cc): """Get the compiler version""" version_re = re.compile(r"IBM XL C/C\+\+.*, V(?P\d*)\.(?P\d*)", re.I).search cmd = cc + ['-qversion'] try: out, err = conf.cmd_and_log(cmd, output=0) except Errors.WafError: conf.fatal('Could not find xlc %r' % cmd) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the XLC version.') k = match.groupdict() conf.env['CC_VERSION'] = (k['major'], k['minor']) # ============ the --as-needed flag should added during the configuration, not at runtime ========= @conf def add_as_needed(self): """ Add ``--as-needed`` to the *LINKFLAGS* """ if self.env.DEST_BINFMT == 'elf' and 'gcc' in (self.env.CXX_NAME, self.env.CC_NAME): self.env.append_unique('LINKFLAGS', '--as-needed') # ============ parallel configuration class cfgtask(Task.TaskBase): """ A task that executes configuration tests make sure that the checks write to conf.env in a thread-safe manner for the moment it only executes conf.check """ def display(self): return '' def runnable_status(self): return Task.RUN_ME def run(self): conf = self.conf bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) bld.env = conf.env bld.init_dirs() bld.in_msg = 1 # suppress top-level start_msg bld.logger = self.logger try: bld.check(**self.args) except: return 1 @conf def multicheck(self, *k, **kw): """ Use tuples to perform parallel configuration tests """ self.start_msg(kw.get('msg', 'Executing %d configuration tests' % len(k))) class par(object): def __init__(self): self.keep = False self.cache_global = Options.cache_global self.nocache = Options.options.nocache self.returned_tasks = [] def total(self): return len(tasks) def to_log(self, *k, **kw): return bld = par() tasks = [] for dct in k: x = cfgtask(bld=bld) tasks.append(x) x.args = dct x.bld = bld x.conf = self x.args = dct # bind a logger that will keep the info in memory x.logger = Logs.make_mem_logger(str(id(x)), self.logger) def it(): yield tasks while 1: yield [] p = Runner.Parallel(bld, Options.options.jobs) p.biter = it() p.start() # flush the logs in order into the config.log for x in tasks: x.logger.memhandler.flush() for x in tasks: if x.hasrun != Task.SUCCESS: self.end_msg(kw.get('errmsg', 'no'), color='YELLOW') self.fatal(kw.get('fatalmsg', None) or 'One of the tests has failed, see the config.log for more information') self.end_msg('ok') debian/waf-1.6/waflib/ansiterm.py0000664000000000000000000001762312145744415013727 0ustar import sys, os try: if not (sys.stderr.isatty() and sys.stdout.isatty()): raise ValueError('not a tty') from ctypes import * class COORD(Structure): _fields_ = [("X", c_short), ("Y", c_short)] class SMALL_RECT(Structure): _fields_ = [("Left", c_short), ("Top", c_short), ("Right", c_short), ("Bottom", c_short)] class CONSOLE_SCREEN_BUFFER_INFO(Structure): _fields_ = [("Size", COORD), ("CursorPosition", COORD), ("Attributes", c_short), ("Window", SMALL_RECT), ("MaximumWindowSize", COORD)] class CONSOLE_CURSOR_INFO(Structure): _fields_ = [('dwSize',c_ulong), ('bVisible', c_int)] sbinfo = CONSOLE_SCREEN_BUFFER_INFO() csinfo = CONSOLE_CURSOR_INFO() hconsole = windll.kernel32.GetStdHandle(-11) windll.kernel32.GetConsoleScreenBufferInfo(hconsole, byref(sbinfo)) if sbinfo.Size.X < 9 or sbinfo.Size.Y < 9: raise ValueError('small console') windll.kernel32.GetConsoleCursorInfo(hconsole, byref(csinfo)) except Exception: pass else: import re, threading is_vista = getattr(sys, "getwindowsversion", None) and sys.getwindowsversion()[0] >= 6 try: _type = unicode except: _type = str to_int = lambda number, default: number and int(number) or default wlock = threading.Lock() STD_OUTPUT_HANDLE = -11 STD_ERROR_HANDLE = -12 class AnsiTerm(object): """ emulate a vt100 terminal in cmd.exe """ def __init__(self): self.encoding = sys.stdout.encoding self.hconsole = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) self.cursor_history = [] self.orig_sbinfo = CONSOLE_SCREEN_BUFFER_INFO() self.orig_csinfo = CONSOLE_CURSOR_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(self.orig_sbinfo)) windll.kernel32.GetConsoleCursorInfo(hconsole, byref(self.orig_csinfo)) def screen_buffer_info(self): sbinfo = CONSOLE_SCREEN_BUFFER_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) return sbinfo def clear_line(self, param): mode = param and int(param) or 0 sbinfo = self.screen_buffer_info() if mode == 1: # Clear from begining of line to cursor position line_start = COORD(0, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X elif mode == 2: # Clear entire line line_start = COORD(sbinfo.CursorPosition.X, sbinfo.CursorPosition.Y) line_length = sbinfo.Size.X - sbinfo.CursorPosition.X else: # Clear from cursor position to end of line line_start = sbinfo.CursorPosition line_length = sbinfo.Size.X - sbinfo.CursorPosition.X chars_written = c_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_wchar(' '), line_length, line_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, line_length, line_start, byref(chars_written)) def clear_screen(self, param): mode = to_int(param, 0) sbinfo = self.screen_buffer_info() if mode == 1: # Clear from begining of screen to cursor position clear_start = COORD(0, 0) clear_length = sbinfo.CursorPosition.X * sbinfo.CursorPosition.Y elif mode == 2: # Clear entire screen and return cursor to home clear_start = COORD(0, 0) clear_length = sbinfo.Size.X * sbinfo.Size.Y windll.kernel32.SetConsoleCursorPosition(self.hconsole, clear_start) else: # Clear from cursor position to end of screen clear_start = sbinfo.CursorPosition clear_length = ((sbinfo.Size.X - sbinfo.CursorPosition.X) + sbinfo.Size.X * (sbinfo.Size.Y - sbinfo.CursorPosition.Y)) chars_written = c_int() windll.kernel32.FillConsoleOutputCharacterA(self.hconsole, c_wchar(' '), clear_length, clear_start, byref(chars_written)) windll.kernel32.FillConsoleOutputAttribute(self.hconsole, sbinfo.Attributes, clear_length, clear_start, byref(chars_written)) def push_cursor(self, param): sbinfo = self.screen_buffer_info() self.cursor_history.append(sbinfo.CursorPosition) def pop_cursor(self, param): if self.cursor_history: old_pos = self.cursor_history.pop() windll.kernel32.SetConsoleCursorPosition(self.hconsole, old_pos) def set_cursor(self, param): y, sep, x = param.partition(';') x = to_int(x, 1) - 1 y = to_int(y, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), min(max(0, y), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def set_column(self, param): x = to_int(param, 1) - 1 sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, x), sbinfo.Size.X), sbinfo.CursorPosition.Y ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_cursor(self, x_offset=0, y_offset=0): sbinfo = self.screen_buffer_info() new_pos = COORD( min(max(0, sbinfo.CursorPosition.X + x_offset), sbinfo.Size.X), min(max(0, sbinfo.CursorPosition.Y + y_offset), sbinfo.Size.Y) ) windll.kernel32.SetConsoleCursorPosition(self.hconsole, new_pos) def move_up(self, param): self.move_cursor(y_offset = -to_int(param, 1)) def move_down(self, param): self.move_cursor(y_offset = to_int(param, 1)) def move_left(self, param): self.move_cursor(x_offset = -to_int(param, 1)) def move_right(self, param): self.move_cursor(x_offset = to_int(param, 1)) def next_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = to_int(param, 1) ) def prev_line(self, param): sbinfo = self.screen_buffer_info() self.move_cursor( x_offset = -sbinfo.CursorPosition.X, y_offset = -to_int(param, 1) ) def rgb2bgr(self, c): return ((c&1) << 2) | (c&2) | ((c&4)>>2) def set_color(self, param): cols = param.split(';') sbinfo = CONSOLE_SCREEN_BUFFER_INFO() windll.kernel32.GetConsoleScreenBufferInfo(self.hconsole, byref(sbinfo)) attr = sbinfo.Attributes for c in cols: if is_vista: c = int(c) else: c = to_int(c, 0) if c in range(30,38): # fgcolor attr = (attr & 0xfff0) | self.rgb2bgr(c-30) elif c in range(40,48): # bgcolor attr = (attr & 0xff0f) | (self.rgb2bgr(c-40) << 4) elif c == 0: # reset attr = self.orig_sbinfo.Attributes elif c == 1: # strong attr |= 0x08 elif c == 4: # blink not available -> bg intensity attr |= 0x80 elif c == 7: # negative attr = (attr & 0xff88) | ((attr & 0x70) >> 4) | ((attr & 0x07) << 4) windll.kernel32.SetConsoleTextAttribute(self.hconsole, attr) def show_cursor(self,param): csinfo.bVisible = 1 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) def hide_cursor(self,param): csinfo.bVisible = 0 windll.kernel32.SetConsoleCursorInfo(self.hconsole, byref(csinfo)) ansi_command_table = { 'A': move_up, 'B': move_down, 'C': move_right, 'D': move_left, 'E': next_line, 'F': prev_line, 'G': set_column, 'H': set_cursor, 'f': set_cursor, 'J': clear_screen, 'K': clear_line, 'h': show_cursor, 'l': hide_cursor, 'm': set_color, 's': push_cursor, 'u': pop_cursor, } # Match either the escape sequence or text not containing escape sequence ansi_tokens = re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') def write(self, text): try: wlock.acquire() for param, cmd, txt in self.ansi_tokens.findall(text): if cmd: cmd_func = self.ansi_command_table.get(cmd) if cmd_func: cmd_func(self, param) else: self.writeconsole(txt) finally: wlock.release() def writeconsole(self, txt): chars_written = c_int() writeconsole = windll.kernel32.WriteConsoleA if isinstance(txt, _type): writeconsole = windll.kernel32.WriteConsoleW TINY_STEP = 3000 for x in range(0, len(txt), TINY_STEP): # According MSDN, size should NOT exceed 64 kb (issue #746) tiny = txt[x : x + TINY_STEP] writeconsole(self.hconsole, tiny, len(tiny), byref(chars_written), None) def flush(self): pass def isatty(self): return True sys.stderr = sys.stdout = AnsiTerm() os.environ['TERM'] = 'vt100' debian/waf-1.6/waflib/Utils.py0000664000000000000000000003301612145744415013177 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Utilities and platform-specific fixes The portability fixes try to provide a consistent behavior of the Waf API through Python versions 2.3 to 3.X and across different platforms (win32, linux, etc) """ import os, sys, errno, traceback, inspect, re, shutil, datetime, gc try: import subprocess except: try: import waflib.extras.subprocess as subprocess except: print("The subprocess module is missing (python2.3?):\n try calling 'waf update --files=subprocess'\n or add a copy of subprocess.py to the python libraries") try: from collections import deque except ImportError: class deque(list): """A deque for Python 2.3 which does not have one""" def popleft(self): return self.pop(0) try: import _winreg as winreg except: try: import winreg except: winreg = None from waflib import Errors try: from collections import UserDict except: from UserDict import UserDict try: from hashlib import md5 except: try: from md5 import md5 except: # never fail to enable fixes from another module pass try: import threading except: class threading(object): """ A fake threading class for platforms lacking the threading module. Use ``waf -j1`` on those platforms """ pass class Lock(object): """Fake Lock class""" def acquire(self): pass def release(self): pass threading.Lock = threading.Thread = Lock else: run_old = threading.Thread.run def run(*args, **kwargs): try: run_old(*args, **kwargs) except (KeyboardInterrupt, SystemExit): raise except: sys.excepthook(*sys.exc_info()) threading.Thread.run = run SIG_NIL = 'iluvcuteoverload'.encode() """Arbitrary null value for a md5 hash. This value must be changed when the hash value is replaced (size)""" O644 = 420 """Constant representing the permissions for regular files (0644 raises a syntax error on python 3)""" O755 = 493 """Constant representing the permissions for executable files (0755 raises a syntax error on python 3)""" rot_chr = ['\\', '|', '/', '-'] "List of characters to use when displaying the throbber (progress bar)" rot_idx = 0 "Index of the current throbber character (progress bar)" try: from collections import defaultdict except ImportError: class defaultdict(dict): """ defaultdict was introduced in python 2.5, so we leave it for python 2.4 and 2.3 """ def __init__(self, default_factory): super(defaultdict, self).__init__() self.default_factory = default_factory def __getitem__(self, key): try: return super(defaultdict, self).__getitem__(key) except KeyError: value = self.default_factory() self[key] = value return value is_win32 = sys.platform in ('win32', 'cli') # we should have put this in the Logs.py file instead :-/ indicator = '\x1b[K%s%s%s\r' if is_win32 and 'NOCOLOR' in os.environ: indicator = '%s%s%s\r' def readf(fname, m='r'): """ Read an entire file into a string, in practice the wrapper node.read(..) should be used instead of this method:: def build(ctx): from waflib import Utils txt = Utils.readf(self.path.find_node('wscript').abspath()) txt = ctx.path.find_node('wscript').read() :type fname: string :param fname: Path to file :type m: string :param m: Open mode :rtype: string :return: Content of the file """ f = open(fname, m) try: txt = f.read() finally: f.close() return txt def h_file(filename): """ Compute a hash value for a file by using md5. This method may be replaced by a faster version if necessary. The following uses the file size and the timestamp value:: import stat from waflib import Utils def h_file(filename): st = os.stat(filename) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') m = Utils.md5() m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(filename) return m.digest() Utils.h_file = h_file :type filename: string :param filename: path to the file to hash :return: hash of the file contents """ f = open(filename, 'rb') m = md5() try: while filename: filename = f.read(100000) m.update(filename) finally: f.close() return m.digest() try: x = ''.encode('hex') except: import binascii def to_hex(s): ret = binascii.hexlify(s) if not isinstance(ret, str): ret = ret.decode('utf-8') return ret else: def to_hex(s): return s.encode('hex') to_hex.__doc__ = """ Return the hexadecimal representation of a string :param s: string to convert :type s: string """ listdir = os.listdir if is_win32: def listdir_win32(s): """ List the contents of a folder in a portable manner. :type s: string :param s: a string, which can be empty on Windows for listing the drive letters """ if not s: try: import ctypes except: # there is nothing much we can do return [x + ':\\' for x in list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')] else: dlen = 4 # length of "?:\\x00" maxdrives = 26 buf = ctypes.create_string_buffer(maxdrives * dlen) ndrives = ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives, ctypes.byref(buf)) return [ buf.raw[4*i:4*i+3].decode('ascii') for i in range(int(ndrives/dlen)) ] if len(s) == 2 and s[1] == ":": s += os.sep if not os.path.isdir(s): e = OSError() e.errno = errno.ENOENT raise e return os.listdir(s) listdir = listdir_win32 def num2ver(ver): """ Convert a string, tuple or version number into an integer. The number is supposed to have at most 4 digits:: from waflib.Utils import num2ver num2ver('1.3.2') == num2ver((1,3,2)) == num2ver((1,3,2,0)) :type ver: string or tuple of numbers :param ver: a version number """ if isinstance(ver, str): ver = tuple(ver.split('.')) if isinstance(ver, tuple): ret = 0 for i in range(4): if i < len(ver): ret += 256**(3 - i) * int(ver[i]) return ret return ver def ex_stack(): """ Extract the stack to display exceptions :return: a string represening the last exception """ exc_type, exc_value, tb = sys.exc_info() exc_lines = traceback.format_exception(exc_type, exc_value, tb) return ''.join(exc_lines) def to_list(sth): """ Convert a string argument to a list by splitting on spaces, and pass through a list argument unchanged:: from waflib.Utils import to_list lst = to_list("a b c d") :param sth: List or a string of items separated by spaces :rtype: list :return: Argument converted to list """ if isinstance(sth, str): return sth.split() else: return sth re_nl = re.compile('\r*\n', re.M) def str_to_dict(txt): """ Parse a string with key = value pairs into a dictionary:: from waflib import Utils x = Utils.str_to_dict(''' a = 1 b = test ''') :type s: string :param s: String to parse :rtype: dict :return: Dictionary containing parsed key-value pairs """ tbl = {} lines = re_nl.split(txt) for x in lines: x = x.strip() if not x or x.startswith('#') or x.find('=') < 0: continue tmp = x.split('=') tbl[tmp[0].strip()] = '='.join(tmp[1:]).strip() return tbl def split_path(path): return path.split('/') def split_path_cygwin(path): if path.startswith('//'): ret = path.split('/')[2:] ret[0] = '/' + ret[0] return ret return path.split('/') re_sp = re.compile('[/\\\\]') def split_path_win32(path): if path.startswith('\\\\'): ret = re.split(re_sp, path)[2:] ret[0] = '\\' + ret[0] return ret return re.split(re_sp, path) if sys.platform == 'cygwin': split_path = split_path_cygwin elif is_win32: split_path = split_path_win32 split_path.__doc__ = """ Split a path by / or \\. This function is not like os.path.split :type path: string :param path: path to split :return: list of strings """ def check_dir(path): """ Ensure that a directory exists (similar to ``mkdir -p``). :type dir: string :param dir: Path to directory """ if not os.path.isdir(path): try: os.makedirs(path) except OSError as e: if not os.path.isdir(path): raise Errors.WafError('Cannot create the folder %r' % path, ex=e) def def_attrs(cls, **kw): """ Set default attributes on a class instance :type cls: class :param cls: the class to update the given attributes in. :type kw: dict :param kw: dictionary of attributes names and values. """ for k, v in kw.items(): if not hasattr(cls, k): setattr(cls, k, v) def quote_define_name(s): """ Convert a string to an identifier suitable for C defines. :type s: string :param s: String to convert :rtype: string :return: Identifier suitable for C defines """ fu = re.compile("[^a-zA-Z0-9]").sub("_", s) fu = fu.upper() return fu def h_list(lst): """ Hash lists. For tuples, using hash(tup) is much more efficient :param lst: list to hash :type lst: list of strings :return: hash of the list """ m = md5() m.update(str(lst).encode()) return m.digest() def h_fun(fun): """ Hash functions :param fun: function to hash :type fun: function :return: hash of the function """ try: return fun.code except AttributeError: try: h = inspect.getsource(fun) except IOError: h = "nocode" try: fun.code = h except AttributeError: pass return h reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") def subst_vars(expr, params): """ Replace ${VAR} with the value of VAR taken from a dict or a config set:: from waflib import Utils s = Utils.subst_vars('${PREFIX}/bin', env) :type expr: string :param expr: String to perform substitution on :param params: Dictionary or config set to look up variable values. """ def repl_var(m): if m.group(1): return '\\' if m.group(2): return '$' try: # ConfigSet instances may contain lists return params.get_flat(m.group(3)) except AttributeError: return params[m.group(3)] return reg_subst.sub(repl_var, expr) def destos_to_binfmt(key): """ Return the binary format based on the unversioned platform name. :param key: platform name :type key: string :return: string representing the binary format """ if key == 'darwin': return 'mac-o' elif key in ('win32', 'cygwin', 'uwin', 'msys'): return 'pe' return 'elf' def unversioned_sys_platform(): """ Return the unversioned platform name. Some Python platform names contain versions, that depend on the build environment, e.g. linux2, freebsd6, etc. This returns the name without the version number. Exceptions are os2 and win32, which are returned verbatim. :rtype: string :return: Unversioned platform name """ s = sys.platform if s == 'java': # The real OS is hidden under the JVM. from java.lang import System s = System.getProperty('os.name') # see http://lopica.sourceforge.net/os.html for a list of possible values if s == 'Mac OS X': return 'darwin' elif s.startswith('Windows '): return 'win32' elif s == 'OS/2': return 'os2' elif s == 'HP-UX': return 'hpux' elif s in ('SunOS', 'Solaris'): return 'sunos' else: s = s.lower() # powerpc == darwin for our purposes if s == 'powerpc': return 'darwin' if s == 'win32' or s.endswith('os2') and s != 'sunos2': return s return re.split('\d+$', s)[0] def nada(*k, **kw): """ A function that does nothing :return: None """ pass class Timer(object): """ Simple object for timing the execution of commands. Its string representation is the current time:: from waflib.Utils import Timer timer = Timer() a_few_operations() s = str(timer) """ def __init__(self): self.start_time = datetime.datetime.utcnow() def __str__(self): delta = datetime.datetime.utcnow() - self.start_time days = int(delta.days) hours = delta.seconds // 3600 minutes = (delta.seconds - hours * 3600) // 60 seconds = delta.seconds - hours * 3600 - minutes * 60 + float(delta.microseconds) / 1000 / 1000 result = '' if days: result += '%dd' % days if days or hours: result += '%dh' % hours if days or hours or minutes: result += '%dm' % minutes return '%s%.3fs' % (result, seconds) if is_win32: old = shutil.copy2 def copy2(src, dst): """ shutil.copy2 does not copy the file attributes on windows, so we hack into the shutil module to fix the problem """ old(src, dst) shutil.copystat(src, dst) setattr(shutil, 'copy2', copy2) if os.name == 'java': # Jython cannot disable the gc but they can enable it ... wtf? try: gc.disable() gc.enable() except NotImplementedError: gc.disable = gc.enable def read_la_file(path): """ Read property files, used by msvc.py :param path: file to read :type path: string """ sp = re.compile(r'^([^=]+)=\'(.*)\'$') dc = {} for line in readf(path).splitlines(): try: _, left, right, _ = sp.split(line.strip()) dc[left] = right except ValueError: pass return dc def nogc(fun): """ Decorator: let a function disable the garbage collector during its execution. It is used in the build context when storing/loading the build cache file (pickle) :param fun: function to execute :type fun: function :return: the return value of the function executed """ def f(*k, **kw): try: gc.disable() ret = fun(*k, **kw) finally: gc.enable() return ret f.__doc__ = fun.__doc__ return f def run_once(fun): """ Decorator: let a function cache its results, use like this:: @run_once def foo(k): return 345*2343 :param fun: function to execute :type fun: function :return: the return value of the function executed """ cache = {} def wrap(k): try: return cache[k] except KeyError: ret = fun(k) cache[k] = ret return ret wrap.__cache__ = cache return wrap def get_registry_app_path(key, filename): if not winreg: return None try: result = winreg.QueryValue(key, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe" % filename[0]) except WindowsError: pass else: if os.path.isfile(result): return result debian/waf-1.6/waflib/__init__.py0000664000000000000000000000010712145744415013631 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.6/waflib/Build.py0000664000000000000000000010704212145744415013137 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ Classes related to the build phase (build, clean, install, step, etc) The inheritance tree is the following: """ import os, sys, errno, re, shutil try: import cPickle except: import pickle as cPickle from waflib import Runner, TaskGen, Utils, ConfigSet, Task, Logs, Options, Context, Errors import waflib.Node CACHE_DIR = 'c4che' """Location of the cache files""" CACHE_SUFFIX = '_cache.py' """Suffix for the cache files""" INSTALL = 1337 """Positive value '->' install, see :py:attr:`waflib.Build.BuildContext.is_install`""" UNINSTALL = -1337 """Negative value '<-' uninstall, see :py:attr:`waflib.Build.BuildContext.is_install`""" SAVED_ATTRS = 'root node_deps raw_deps task_sigs'.split() """Build class members to save between the runs (root, node_deps, raw_deps, task_sigs)""" CFG_FILES = 'cfg_files' """Files from the build directory to hash before starting the build (``config.h`` written during the configuration)""" POST_AT_ONCE = 0 """Post mode: all task generators are posted before the build really starts""" POST_LAZY = 1 """Post mode: post the task generators group after group""" POST_BOTH = 2 """Post mode: post the task generators at once, then re-check them for each group""" class BuildContext(Context.Context): '''executes the build''' cmd = 'build' variant = '' def __init__(self, **kw): super(BuildContext, self).__init__(**kw) self.is_install = 0 """Non-zero value when installing or uninstalling file""" self.top_dir = kw.get('top_dir', Context.top_dir) self.run_dir = kw.get('run_dir', Context.run_dir) self.post_mode = POST_AT_ONCE """post the task generators at once, group-by-group, or both""" # output directory - may be set until the nodes are considered self.out_dir = kw.get('out_dir', Context.out_dir) self.cache_dir = kw.get('cache_dir', None) if not self.cache_dir: self.cache_dir = self.out_dir + os.sep + CACHE_DIR # map names to environments, the '' must be defined self.all_envs = {} # ======================================= # # cache variables self.task_sigs = {} """Signatures of the tasks (persists between build executions)""" self.node_deps = {} """Dict of node dependencies found by :py:meth:`waflib.Task.Task.scan` (persists between build executions)""" self.raw_deps = {} """Dict of custom data returned by :py:meth:`waflib.Task.Task.scan` (persists between build executions)""" # list of folders that are already scanned # so that we do not need to stat them one more time self.cache_dir_contents = {} self.task_gen_cache_names = {} self.launch_dir = Context.launch_dir self.jobs = Options.options.jobs self.targets = Options.options.targets self.keep = Options.options.keep self.cache_global = Options.cache_global self.nocache = Options.options.nocache self.progress_bar = Options.options.progress_bar ############ stuff below has not been reviewed # Manual dependencies. self.deps_man = Utils.defaultdict(list) """Manual dependencies set by :py:meth:`waflib.Build.BuildContext.add_manual_dependency`""" # just the structure here self.current_group = 0 """ Current build group """ self.groups = [] """ List containing lists of task generators """ self.group_names = {} """ Map group names to the group lists. See :py:meth:`waflib.Build.BuildContext.add_group` """ def get_variant_dir(self): """Getter for the variant_dir attribute""" if not self.variant: return self.out_dir return os.path.join(self.out_dir, self.variant) variant_dir = property(get_variant_dir, None) def __call__(self, *k, **kw): """ Create a task generator and add it to the current build group. The following forms are equivalent:: def build(bld): tg = bld(a=1, b=2) def build(bld): tg = bld() tg.a = 1 tg.b = 2 def build(bld): tg = TaskGen.task_gen(a=1, b=2) bld.add_to_group(tg, None) :param group: group name to add the task generator to :type group: string """ kw['bld'] = self ret = TaskGen.task_gen(*k, **kw) self.task_gen_cache_names = {} # reset the cache, each time self.add_to_group(ret, group=kw.get('group', None)) return ret def __copy__(self): """Implemented to prevents copies of build contexts (raises an exception)""" raise Errors.WafError('build contexts are not supposed to be copied') def install_files(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.install_files`""" pass def install_as(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.install_as`""" pass def symlink_as(self, *k, **kw): """Actual implementation provided by :py:meth:`waflib.Build.InstallContext.symlink_as`""" pass def load_envs(self): """ The configuration command creates files of the form ``build/c4che/NAMEcache.py``. This method creates a :py:class:`waflib.ConfigSet.ConfigSet` instance for each ``NAME`` by reading those files. The config sets are then stored in the dict :py:attr:`waflib.Build.BuildContext.allenvs`. """ node = self.root.find_node(self.cache_dir) if not node: raise Errors.WafError('The project was not configured: run "waf configure" first!') lst = node.ant_glob('**/*%s' % CACHE_SUFFIX, quiet=True) if not lst: raise Errors.WafError('The cache directory is empty: reconfigure the project') for x in lst: name = x.path_from(node).replace(CACHE_SUFFIX, '').replace('\\', '/') env = ConfigSet.ConfigSet(x.abspath()) self.all_envs[name] = env for f in env[CFG_FILES]: newnode = self.root.find_resource(f) try: h = Utils.h_file(newnode.abspath()) except (IOError, AttributeError): Logs.error('cannot find %r' % f) h = Utils.SIG_NIL newnode.sig = h def init_dirs(self): """ Initialize the project directory and the build directory by creating the nodes :py:attr:`waflib.Build.BuildContext.srcnode` and :py:attr:`waflib.Build.BuildContext.bldnode` corresponding to ``top_dir`` and ``variant_dir`` respectively. The ``bldnode`` directory will be created if it does not exist. """ if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') self.path = self.srcnode = self.root.find_dir(self.top_dir) self.bldnode = self.root.make_node(self.variant_dir) self.bldnode.mkdir() def execute(self): """ Restore the data from previous builds and call :py:meth:`waflib.Build.BuildContext.execute_build`. Overrides from :py:func:`waflib.Context.Context.execute` """ self.restore() if not self.all_envs: self.load_envs() self.execute_build() def execute_build(self): """ Execute the build by: * reading the scripts (see :py:meth:`waflib.Context.Context.recurse`) * calling :py:meth:`waflib.Build.BuildContext.pre_build` to call user build functions * calling :py:meth:`waflib.Build.BuildContext.compile` to process the tasks * calling :py:meth:`waflib.Build.BuildContext.post_build` to call user build functions """ Logs.info("Waf: Entering directory `%s'" % self.variant_dir) self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() if self.progress_bar: sys.stderr.write(Logs.colors.cursor_off) try: self.compile() finally: if self.progress_bar == 1: c = len(self.returned_tasks) or 1 self.to_log(self.progress_line(c, c, Logs.colors.BLUE, Logs.colors.NORMAL)) print('') sys.stdout.flush() sys.stderr.write(Logs.colors.cursor_on) Logs.info("Waf: Leaving directory `%s'" % self.variant_dir) self.post_build() def restore(self): """ Load the data from a previous run, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS` """ try: env = ConfigSet.ConfigSet(os.path.join(self.cache_dir, 'build.config.py')) except (IOError, OSError): pass else: if env['version'] < Context.HEXVERSION: raise Errors.WafError('Version mismatch! reconfigure the project') for t in env['tools']: self.setup(**t) f = None try: dbfn = os.path.join(self.variant_dir, Context.DBFILE) try: f = open(dbfn, 'rb') except (IOError, EOFError): # handle missing file/empty file Logs.debug('build: could not load the build cache %s (missing)' % dbfn) else: try: waflib.Node.pickle_lock.acquire() waflib.Node.Nod3 = self.node_class try: data = cPickle.load(f) except Exception as e: Logs.debug('build: could not pickle the build cache %s: %r' % (dbfn, e)) else: for x in SAVED_ATTRS: setattr(self, x, data[x]) finally: waflib.Node.pickle_lock.release() finally: if f: f.close() self.init_dirs() def store(self): """ Store the data for next runs, sets the attributes listed in :py:const:`waflib.Build.SAVED_ATTRS`. Uses a temporary file to avoid problems on ctrl+c. """ data = {} for x in SAVED_ATTRS: data[x] = getattr(self, x) db = os.path.join(self.variant_dir, Context.DBFILE) try: waflib.Node.pickle_lock.acquire() waflib.Node.Nod3 = self.node_class f = None try: f = open(db + '.tmp', 'wb') cPickle.dump(data, f) finally: if f: f.close() finally: waflib.Node.pickle_lock.release() try: st = os.stat(db) os.unlink(db) if not Utils.is_win32: # win32 has no chown but we're paranoid os.chown(db + '.tmp', st.st_uid, st.st_gid) except (AttributeError, OSError): pass # do not use shutil.move (copy is not thread-safe) os.rename(db + '.tmp', db) def compile(self): """ Run the build by creating an instance of :py:class:`waflib.Runner.Parallel` The cache file is not written if the build is up to date (no task executed). """ Logs.debug('build: compile()') # use another object to perform the producer-consumer logic (reduce the complexity) self.producer = Runner.Parallel(self, self.jobs) self.producer.biter = self.get_build_iterator() self.returned_tasks = [] # not part of the API yet try: self.producer.start() except KeyboardInterrupt: self.store() raise else: if self.producer.dirty: self.store() if self.producer.error: raise Errors.BuildError(self.producer.error) def setup(self, tool, tooldir=None, funs=None): """ Import waf tools, used to import those accessed during the configuration:: def configure(conf): conf.load('glib2') def build(bld): pass # glib2 is imported implicitly :param tool: tool list :type tool: list :param tooldir: optional tool directory (sys.path) :type tooldir: list of string :param funs: unused variable """ if isinstance(tool, list): for i in tool: self.setup(i, tooldir) return module = Context.load_tool(tool, tooldir) if hasattr(module, "setup"): module.setup(self) def get_env(self): """Getter for the env property""" try: return self.all_envs[self.variant] except KeyError: return self.all_envs[''] def set_env(self, val): """Setter for the env property""" self.all_envs[self.variant] = val env = property(get_env, set_env) def add_manual_dependency(self, path, value): """ Adds a dependency from a node object to a value:: def build(bld): bld.add_manual_dependency( bld.path.find_resource('wscript'), bld.root.find_resource('/etc/fstab')) :param path: file path :type path: string or :py:class:`waflib.Node.Node` :param value: value to depend on :type value: :py:class:`waflib.Node.Node`, string, or function returning a string """ if isinstance(path, waflib.Node.Node): node = path elif os.path.isabs(path): node = self.root.find_resource(path) else: node = self.path.find_resource(path) self.deps_man[id(node)].append(value) def launch_node(self): """Returns the launch directory as a :py:class:`waflib.Node.Node` object""" try: # private cache return self.p_ln except AttributeError: self.p_ln = self.root.find_dir(self.launch_dir) return self.p_ln def hash_env_vars(self, env, vars_lst): """ Hash configuration set variables:: def build(bld): bld.hash_env_vars(bld.env, ['CXX', 'CC']) :param env: Configuration Set :type env: :py:class:`waflib.ConfigSet.ConfigSet` :param vars_lst: list of variables :type vars_list: list of string """ if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass lst = [env[a] for a in vars_lst] ret = Utils.h_list(lst) Logs.debug('envhash: %s %r', Utils.to_hex(ret), lst) cache[idx] = ret return ret def get_tgen_by_name(self, name): """ Retrieves a task generator from its name or its target name the name must be unique:: def build(bld): tg = bld(name='foo') tg == bld.get_tgen_by_name('foo') """ cache = self.task_gen_cache_names if not cache: # create the index lazily for g in self.groups: for tg in g: try: cache[tg.name] = tg except AttributeError: # raised if not a task generator, which should be uncommon pass try: return cache[name] except KeyError: raise Errors.WafError('Could not find a task generator for the name %r' % name) def progress_line(self, state, total, col1, col2): """ Compute the progress bar used by ``waf -p`` """ n = len(str(total)) Utils.rot_idx += 1 ind = Utils.rot_chr[Utils.rot_idx % 4] pc = (100.*state)/total eta = str(self.timer) fs = "[%%%dd/%%%dd][%%s%%2d%%%%%%s][%s][" % (n, n, ind) left = fs % (state, total, col1, pc, col2) right = '][%s%s%s]' % (col1, eta, col2) cols = Logs.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) if cols < 7: cols = 7 ratio = ((cols*state)//total) - 1 bar = ('='*ratio+'>').ljust(cols) msg = Utils.indicator % (left, bar, right) return msg def declare_chain(self, *k, **kw): """ Wrapper for :py:func:`waflib.TaskGen.declare_chain` provided for convenience """ return TaskGen.declare_chain(*k, **kw) def pre_build(self): """Execute user-defined methods before the build starts, see :py:meth:`waflib.Build.BuildContext.add_pre_fun`""" for m in getattr(self, 'pre_funs', []): m(self) def post_build(self): """Executes the user-defined methods after the build is successful, see :py:meth:`waflib.Build.BuildContext.add_post_fun`""" for m in getattr(self, 'post_funs', []): m(self) def add_pre_fun(self, meth): """ Bind a method to execute after the scripts are read and before the build starts:: def mycallback(bld): print("Hello, world!") def build(bld): bld.add_pre_fun(mycallback) """ try: self.pre_funs.append(meth) except AttributeError: self.pre_funs = [meth] def add_post_fun(self, meth): """ Bind a method to execute immediately after the build is successful:: def call_ldconfig(bld): bld.exec_command('/sbin/ldconfig') def build(bld): if bld.cmd == 'install': bld.add_pre_fun(call_ldconfig) """ try: self.post_funs.append(meth) except AttributeError: self.post_funs = [meth] def get_group(self, x): """ Get the group x, or return the current group if x is None :param x: name or number or None :type x: string, int or None """ if not self.groups: self.add_group() if x is None: return self.groups[self.current_group] if x in self.group_names: return self.group_names[x] return self.groups[x] def add_to_group(self, tgen, group=None): """add a task or a task generator for the build""" # paranoid assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.TaskBase)) tgen.bld = self self.get_group(group).append(tgen) def get_group_name(self, g): """name for the group g (utility)""" if not isinstance(g, list): g = self.groups[g] for x in self.group_names: if id(self.group_names[x]) == id(g): return x return '' def get_group_idx(self, tg): """ Index of the group containing the task generator given as argument:: def build(bld): tg = bld(name='nada') 0 == bld.get_group_idx(tg) :param tg: Task generator object :type tg: :py:class:`waflib.TaskGen.task_gen` """ se = id(tg) for i in range(len(self.groups)): for t in self.groups[i]: if id(t) == se: return i return None def add_group(self, name=None, move=True): """ Add a new group of tasks/task generators. By default the new group becomes the default group for new task generators. :param name: name for this group :type name: string :param move: set the group created as default group (True by default) :type move: bool """ #if self.groups and not self.groups[0].tasks: # error('add_group: an empty group is already present') if name and name in self.group_names: Logs.error('add_group: name %s already present' % name) g = [] self.group_names[name] = g self.groups.append(g) if move: self.current_group = len(self.groups) - 1 def set_group(self, idx): """ Set the current group to be idx: now new task generators will be added to this group by default:: def build(bld): bld(rule='touch ${TGT}', target='foo.txt') bld.add_group() # now the current group is 1 bld(rule='touch ${TGT}', target='bar.txt') bld.set_group(0) # now the current group is 0 bld(rule='touch ${TGT}', target='truc.txt') # build truc.txt before bar.txt :param idx: group name or group index :type idx: string or int """ if isinstance(idx, str): g = self.group_names[idx] for i in range(len(self.groups)): if id(g) == id(self.groups[i]): self.current_group = i else: self.current_group = idx def total(self): """ Approximate task count: this value may be inaccurate if task generators are posted lazily (see :py:attr:`waflib.Build.BuildContext.post_mode`). The value :py:attr:`waflib.Runner.Parallel.total` is updated during the task execution. """ total = 0 for group in self.groups: for tg in group: try: total += len(tg.tasks) except AttributeError: total += 1 return total def get_targets(self): """ Return the task generator corresponding to the 'targets' list, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator`:: $ waf --targets=myprogram,myshlib """ to_post = [] min_grp = 0 for name in self.targets.split(','): tg = self.get_tgen_by_name(name) if not tg: raise Errors.WafError('target %r does not exist' % name) m = self.get_group_idx(tg) if m > min_grp: min_grp = m to_post = [tg] elif m == min_grp: to_post.append(tg) return (min_grp, to_post) def post_group(self): """ Post the task generators from the group indexed by self.cur, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ if self.targets == '*': for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: f() elif self.targets: if self.cur < self._min_grp: for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: f() else: for tg in self._exact_tg: tg.post() else: ln = self.launch_node() for tg in self.groups[self.cur]: try: f = tg.post except AttributeError: pass else: if tg.path.is_child_of(ln): f() def get_tasks_group(self, idx): """ Return all the tasks for the group of num idx, used by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ tasks = [] for tg in self.groups[idx]: # TODO a try-except might be more efficient if isinstance(tg, Task.TaskBase): tasks.append(tg) else: tasks.extend(tg.tasks) return tasks def get_build_iterator(self): """ Creates a generator object that returns lists of tasks executable in parallel (yield) :return: tasks which can be executed immediatly :rtype: list of :py:class:`waflib.Task.TaskBase` """ self.cur = 0 if self.targets and self.targets != '*': (self._min_grp, self._exact_tg) = self.get_targets() global lazy_post if self.post_mode != POST_LAZY: while self.cur < len(self.groups): self.post_group() self.cur += 1 self.cur = 0 while self.cur < len(self.groups): # first post the task generators for the group if self.post_mode != POST_AT_ONCE: self.post_group() # then extract the tasks tasks = self.get_tasks_group(self.cur) # if the constraints are set properly (ext_in/ext_out, before/after) # the call to set_file_constraints may be removed (can be a 15% penalty on no-op rebuilds) # (but leave set_file_constraints for the installation step) # # if the tasks have only files, set_file_constraints is required but set_precedence_constraints is not necessary # Task.set_file_constraints(tasks) Task.set_precedence_constraints(tasks) self.cur_tasks = tasks self.cur += 1 if not tasks: # return something else the build will stop continue yield tasks while 1: yield [] #def install_dir(self, path, env=None): # """ # Create empty folders for the installation (very rarely used) TODO # """ # return class inst(Task.Task): """ Special task used for installing files and symlinks, it behaves both like a task and like a task generator """ color = 'CYAN' def post(self): """ Same interface as in :py:meth:`waflib.TaskGen.task_gen.post` """ buf = [] for x in self.source: if isinstance(x, waflib.Node.Node): y = x else: y = self.path.find_resource(x) if not y: if Logs.verbose: Logs.warn('Could not find %s immediately (may cause broken builds)' % x) idx = self.generator.bld.get_group_idx(self) for tg in self.generator.bld.groups[idx]: if not isinstance(tg, inst) and id(tg) != id(self): tg.post() y = self.path.find_resource(x) if y: break else: raise Errors.WafError('could not find %r in %r' % (x, self.path)) buf.append(y) self.inputs = buf def runnable_status(self): """ Installation tasks are always executed, so this method returns either :py:const:`waflib.Task.ASK_LATER` or :py:const:`waflib.Task.RUN_ME`. """ ret = super(inst, self).runnable_status() if ret == Task.SKIP_ME: return Task.RUN_ME return ret def __str__(self): """Return an empty string to disable the display""" return '' def run(self): """The attribute 'exec_task' holds the method to execute""" return self.generator.exec_task() def get_install_path(self, destdir=True): """ Installation path obtained from ``self.dest`` and prefixed by the destdir. The variables such as '${PREFIX}/bin' are substituted. """ dest = Utils.subst_vars(self.dest, self.env) dest = dest.replace('/', os.sep) if destdir and Options.options.destdir: dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) return dest def exec_install_files(self): """ Predefined method for installing files """ destpath = self.get_install_path() if not destpath: raise Errors.WafError('unknown installation path %r' % self.generator) for x, y in zip(self.source, self.inputs): if self.relative_trick: destfile = os.path.join(destpath, y.path_from(self.path)) Utils.check_dir(os.path.dirname(destfile)) else: destfile = os.path.join(destpath, y.name) self.generator.bld.do_install(y.abspath(), destfile, self.chmod) def exec_install_as(self): """ Predefined method for installing one file with a given name """ destfile = self.get_install_path() self.generator.bld.do_install(self.inputs[0].abspath(), destfile, self.chmod) def exec_symlink_as(self): """ Predefined method for installing a symlink """ destfile = self.get_install_path() self.generator.bld.do_link(self.link, destfile) class InstallContext(BuildContext): '''installs the targets on the system''' cmd = 'install' def __init__(self, **kw): super(InstallContext, self).__init__(**kw) # list of targets to uninstall for removing the empty folders after uninstalling self.uninstall = [] self.is_install = INSTALL def do_install(self, src, tgt, chmod=Utils.O644): """ Copy a file from src to tgt with given file permissions. The actual copy is not performed if the source and target file have the same size and the same timestamps. When the copy occurs, the file is first removed and then copied (prevent stale inodes). This method is overridden in :py:meth:`waflib.Build.UninstallContext.do_install` to remove the file. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string :param chmod: installation mode :type chmod: int """ d, _ = os.path.split(tgt) if not d: raise Errors.WafError('Invalid installation given %r->%r' % (src, tgt)) Utils.check_dir(d) srclbl = src.replace(self.srcnode.abspath() + os.sep, '') if not Options.options.force: # check if the file is already there to avoid a copy try: st1 = os.stat(tgt) st2 = os.stat(src) except OSError: pass else: # same size and identical timestamps -> make no copy if st1.st_mtime + 2 >= st2.st_mtime and st1.st_size == st2.st_size: if not self.progress_bar: Logs.info('- install %s (from %s)' % (tgt, srclbl)) return False if not self.progress_bar: Logs.info('+ install %s (from %s)' % (tgt, srclbl)) # following is for shared libs and stale inodes (-_-) try: os.remove(tgt) except OSError: pass try: shutil.copy2(src, tgt) os.chmod(tgt, chmod) except IOError: try: os.stat(src) except (OSError, IOError): Logs.error('File %r does not exist' % src) raise Errors.WafError('Could not install the file %r' % tgt) def do_link(self, src, tgt): """ Create a symlink from tgt to src. This method is overridden in :py:meth:`waflib.Build.UninstallContext.do_link` to remove the symlink. :param src: file name as absolute path :type src: string :param tgt: file destination, as absolute path :type tgt: string """ d, _ = os.path.split(tgt) Utils.check_dir(d) link = False if not os.path.islink(tgt): link = True elif os.readlink(tgt) != src: link = True if link: try: os.remove(tgt) except OSError: pass if not self.progress_bar: Logs.info('+ symlink %s (to %s)' % (tgt, src)) os.symlink(src, tgt) else: if not self.progress_bar: Logs.info('- symlink %s (to %s)' % (tgt, src)) def run_task_now(self, tsk, postpone): """ This method is called by :py:meth:`waflib.Build.InstallContext.install_files`, :py:meth:`waflib.Build.InstallContext.install_as` and :py:meth:`waflib.Build.InstallContext.symlink_as` immediately after the installation task is created. Its role is to force the immediate execution if necessary, that is when ``postpone=False`` was given. """ tsk.post() if not postpone: if tsk.runnable_status() == Task.ASK_LATER: raise self.WafError('cannot post the task %r' % tsk) tsk.run() def install_files(self, dest, files, env=None, chmod=Utils.O644, relative_trick=False, cwd=None, add=True, postpone=True): """ Create a task to install files on the system:: def build(bld): bld.install_files('${DATADIR}', self.path.find_resource('wscript')) :param dest: absolute path of the destination directory :type dest: string :param files: input files :type files: list of strings or list of nodes :param env: configuration set for performing substitutions in dest :type env: Configuration set :param relative_trick: preserve the folder hierarchy when installing whole folders :type relative_trick: bool :param cwd: parent node for searching srcfile, when srcfile is not a :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool """ tsk = inst(env=env or self.env) tsk.bld = self tsk.path = cwd or self.path tsk.chmod = chmod if isinstance(files, waflib.Node.Node): tsk.source = [files] else: tsk.source = Utils.to_list(files) tsk.dest = dest tsk.exec_task = tsk.exec_install_files tsk.relative_trick = relative_trick if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk def install_as(self, dest, srcfile, env=None, chmod=Utils.O644, cwd=None, add=True, postpone=True): """ Create a task to install a file on the system with a different name:: def build(bld): bld.install_as('${PREFIX}/bin', 'myapp', chmod=Utils.O755) :param dest: absolute path of the destination file :type dest: string :param srcfile: input file :type srcfile: string or node :param cwd: parent node for searching srcfile, when srcfile is not a :py:class:`waflib.Node.Node` :type cwd: :py:class:`waflib.Node.Node` :param env: configuration set for performing substitutions in dest :type env: Configuration set :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool """ tsk = inst(env=env or self.env) tsk.bld = self tsk.path = cwd or self.path tsk.chmod = chmod tsk.source = [srcfile] tsk.dest = dest tsk.exec_task = tsk.exec_install_as if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk def symlink_as(self, dest, src, env=None, cwd=None, add=True, postpone=True): """ Create a task to install a symlink:: def build(bld): bld.symlink_as('${PREFIX}/lib/libfoo.so', 'libfoo.so.1.2.3') :param dest: absolute path of the symlink :type dest: string :param src: absolute or relative path of the link :type src: string :param env: configuration set for performing substitutions in dest :type env: Configuration set :param add: add the task created to a build group - set ``False`` only if the installation task is created after the build has started :type add: bool :param postpone: execute the task immediately to perform the installation :type postpone: bool """ if Utils.is_win32: # symlinks *cannot* work on that platform return tsk = inst(env=env or self.env) tsk.bld = self tsk.dest = dest tsk.path = cwd or self.path tsk.source = [] tsk.link = src tsk.exec_task = tsk.exec_symlink_as if add: self.add_to_group(tsk) self.run_task_now(tsk, postpone) return tsk class UninstallContext(InstallContext): '''removes the targets installed''' cmd = 'uninstall' def __init__(self, **kw): super(UninstallContext, self).__init__(**kw) self.is_install = UNINSTALL def do_install(self, src, tgt, chmod=Utils.O644): """See :py:meth:`waflib.Build.InstallContext.do_install`""" if not self.progress_bar: Logs.info('- remove %s' % tgt) self.uninstall.append(tgt) try: os.remove(tgt) except OSError as e: if e.errno != errno.ENOENT: if not getattr(self, 'uninstall_error', None): self.uninstall_error = True Logs.warn('build: some files could not be uninstalled (retry with -vv to list them)') if Logs.verbose > 1: Logs.warn('could not remove %s (error code %r)' % (e.filename, e.errno)) # TODO ita refactor this into a post build action to uninstall the folders (optimization) while tgt: tgt = os.path.dirname(tgt) try: os.rmdir(tgt) except OSError: break def do_link(self, src, tgt): """See :py:meth:`waflib.Build.InstallContext.do_link`""" try: if not self.progress_bar: Logs.info('- unlink %s' % tgt) os.remove(tgt) except OSError: pass # TODO ita refactor this into a post build action to uninstall the folders (optimization)? while tgt: tgt = os.path.dirname(tgt) try: os.rmdir(tgt) except OSError: break def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ try: # do not execute any tasks def runnable_status(self): return Task.SKIP_ME setattr(Task.Task, 'runnable_status_back', Task.Task.runnable_status) setattr(Task.Task, 'runnable_status', runnable_status) super(UninstallContext, self).execute() finally: setattr(Task.Task, 'runnable_status', Task.Task.runnable_status_back) class CleanContext(BuildContext): '''cleans the project''' cmd = 'clean' def execute(self): """ See :py:func:`waflib.Context.Context.execute` """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) try: self.clean() finally: self.store() def clean(self): """clean the data and some files in the build dir .. well, TODO""" Logs.debug('build: clean called') if self.bldnode != self.srcnode: # would lead to a disaster if top == out lst = [self.root.find_or_declare(f) for f in self.env[CFG_FILES]] for n in self.bldnode.ant_glob('**/*', excl='lock* *conf_check_*/** config.log c4che/*', quiet=True): if n in lst: continue n.delete() self.root.children = {} for v in 'node_deps task_sigs raw_deps'.split(): setattr(self, v, {}) class ListContext(BuildContext): '''lists the targets to execute''' cmd = 'list' def execute(self): """ See :py:func:`waflib.Context.Context.execute`. """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) self.pre_build() # display the time elapsed in the progress bar self.timer = Utils.Timer() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() try: # force the cache initialization self.get_tgen_by_name('') except: pass lst = list(self.task_gen_cache_names.keys()) lst.sort() for k in lst: Logs.pprint('GREEN', k) class StepContext(BuildContext): '''executes tasks in a step-by-step fashion, for debugging''' cmd = 'step' def __init__(self, **kw): super(StepContext, self).__init__(**kw) self.files = Options.options.files def compile(self): """ Compile the tasks matching the input/output files given (regular expression matching). Derived from :py:meth:`waflib.Build.BuildContext.compile`:: $ waf step --files=foo.c,bar.c,in:truc.c,out:bar.o $ waf step --files=in:foo.cpp.1.o # link task only """ if not self.files: Logs.warn('Add a pattern for the debug build, for example "waf step --files=main.c,app"') BuildContext.compile(self) return for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.TaskBase): lst = [tg] else: lst = tg.tasks for tsk in lst: do_exec = False for node in getattr(tsk, 'inputs', []): if matcher(node, output=False): do_exec = True break for node in getattr(tsk, 'outputs', []): if matcher(node, output=True): do_exec = True break if do_exec: ret = tsk.run() Logs.info('%s -> exit %r' % (str(tsk), ret)) def get_matcher(self, pat): # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output == True and not out: return False if output == False and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match BuildContext.store = Utils.nogc(BuildContext.store) BuildContext.restore = Utils.nogc(BuildContext.restore) debian/waf-1.6/waflib/ConfigSet.py0000664000000000000000000001730412145744415013762 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ ConfigSet: a special dict The values put in :py:class:`ConfigSet` must be lists """ import copy, re, os from waflib import Logs, Utils re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) class ConfigSet(object): """ A dict that honor serialization and parent relationships. The serialization format is human-readable (python-like) and performed by using eval() and repr(). For high performance prefer pickle. Do not store functions as they are not serializable. The values can be accessed by attributes or by keys:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.FOO = 'test' env['FOO'] = 'test' """ __slots__ = ('table', 'parent') def __init__(self, filename=None): self.table = {} """ Internal dict holding the object values """ #self.parent = None if filename: self.load(filename) def __contains__(self, key): """ Enable the *in* syntax:: if 'foo' in env: print env['foo'] """ if key in self.table: return True try: return self.parent.__contains__(key) except AttributeError: return False # parent may not exist def keys(self): """Dict interface (unknown purpose)""" keys = set() cur = self while cur: keys.update(cur.table.keys()) cur = getattr(cur, 'parent', None) keys = list(keys) keys.sort() return keys def __str__(self): """Text representation of the ConfigSet (for debugging purposes)""" return "\n".join(["%r %r" % (x, self.__getitem__(x)) for x in self.keys()]) def __getitem__(self, key): """ Dictionary interface: get value from key:: def configure(conf): conf.env['foo'] = {} print(env['foo']) """ try: while 1: x = self.table.get(key, None) if not x is None: return x self = self.parent except AttributeError: return [] def __setitem__(self, key, value): """ Dictionary interface: get value from key """ self.table[key] = value def __delitem__(self, key): """ Dictionary interface: get value from key """ self[key] = [] def __getattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value conf.env['value'] """ if name in self.__slots__: return object.__getattr__(self, name) else: return self[name] def __setattr__(self, name, value): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): conf.env.value = x env['value'] = x """ if name in self.__slots__: object.__setattr__(self, name, value) else: self[name] = value def __delattr__(self, name): """ Attribute access provided for convenience. The following forms are equivalent:: def configure(conf): del env.value del env['value'] """ if name in self.__slots__: object.__delattr__(self, name) else: del self[name] def derive(self): """ Returns a new ConfigSet deriving from self. The copy returned will be a shallow copy:: from waflib.ConfigSet import ConfigSet env = ConfigSet() env.append_value('CFLAGS', ['-O2']) child = env.derive() child.CFLAGS.append('test') # warning! this will modify 'env' child.CFLAGS = ['-O3'] # new list, ok child.append_value('CFLAGS', ['-O3']) # ok Use :py:func:`ConfigSet.detach` to detach the child from the parent. """ newenv = ConfigSet() newenv.parent = self return newenv def detach(self): """ Detach self from its parent (if existing) Modifying the parent :py:class:`ConfigSet` will not change the current object Modifying this :py:class:`ConfigSet` will not modify the parent one. """ tbl = self.get_merged_dict() try: delattr(self, 'parent') except AttributeError: pass else: keys = tbl.keys() for x in keys: tbl[x] = copy.deepcopy(tbl[x]) self.table = tbl def get_flat(self, key): """ Return a value as a string. If the input is a list, the value returned is space-separated. :param key: key to use :type key: string """ s = self[key] if isinstance(s, str): return s return ' '.join(s) def _get_list_value_for_modification(self, key): """ Return a list value for further modification. The list may be modified inplace and there is no need to do this afterwards:: self.table[var] = value """ try: value = self.table[key] except KeyError: try: value = self.parent[key] except AttributeError: value = [] if isinstance(value, list): value = value[:] else: value = [value] else: if not isinstance(value, list): value = [value] self.table[key] = value return value def append_value(self, var, val): """ Appends a value to the specified config key:: def build(bld): bld.env.append_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ current_value = self._get_list_value_for_modification(var) if isinstance(val, str): # if there were string everywhere we could optimize this val = [val] current_value.extend(val) def prepend_value(self, var, val): """ Prepends a value to the specified item:: def configure(conf): conf.env.prepend_value('CFLAGS', ['-O2']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] self.table[var] = val + self._get_list_value_for_modification(var) def append_unique(self, var, val): """ Append a value to the specified item only if it's not already present:: def build(bld): bld.env.append_unique('CFLAGS', ['-O2', '-g']) The value must be a list or a tuple """ if isinstance(val, str): val = [val] current_value = self._get_list_value_for_modification(var) for x in val: if x not in current_value: current_value.append(x) def get_merged_dict(self): """ Compute the merged dictionary from the fusion of self and all its parent :rtype: a ConfigSet object """ table_list = [] env = self while 1: table_list.insert(0, env.table) try: env = env.parent except AttributeError: break merged_table = {} for table in table_list: merged_table.update(table) return merged_table def store(self, filename): """ Write the :py:class:`ConfigSet` data into a file. See :py:meth:`ConfigSet.load` for reading such files. :param filename: file to use :type filename: string """ try: os.makedirs(os.path.split(filename)[0]) except OSError: pass f = None try: f = open(filename, 'w') merged_table = self.get_merged_dict() keys = list(merged_table.keys()) keys.sort() for k in keys: if k != 'undo_stack': f.write('%s = %r\n' % (k, merged_table[k])) finally: if f: f.close() def load(self, filename): """ Retrieve the :py:class:`ConfigSet` data from a file. See :py:meth:`ConfigSet.store` for writing such files :param filename: file to use :type filename: string """ tbl = self.table code = Utils.readf(filename) for m in re_imp.finditer(code): g = m.group tbl[g(2)] = eval(g(3)) Logs.debug('env: %s' % str(self.table)) def update(self, d): """ Dictionary interface: replace values from another dict :param d: object to use the value from :type d: dict-like object """ for k, v in d.items(): self[k] = v def stash(self): """ Store the object state, to provide a kind of transaction support:: env = ConfigSet() env.stash() try: env.append_value('CFLAGS', '-O3') call_some_method(env) finally: env.revert() The history is kept in a stack, and is lost during the serialization by :py:meth:`ConfigSet.store` """ self.undo_stack = self.undo_stack + [self.table] self.table = self.table.copy() def revert(self): """ Reverts the object to a previous state. See :py:meth:`ConfigSet.stash` """ self.table = self.undo_stack.pop(-1) debian/waf-1.6/waflib/Context.py0000664000000000000000000003766412145744415013540 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Classes and functions required for waf commands """ import os, imp, sys from waflib import Utils, Errors, Logs import waflib.Node # the following 3 constants are updated on each new release (do not touch) HEXVERSION=0x1060b00 """Constant updated on new releases""" WAFVERSION="1.6.11" """Constant updated on new releases""" WAFREVISION="a7e69d6b81b04729804754c4d5214da063779a65" """Constant updated on new releases""" ABI = 98 """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" DBFILE = '.wafpickle-%d' % ABI """Name of the pickle file for storing the build data""" APPNAME = 'APPNAME' """Default application name (used by ``waf dist``)""" VERSION = 'VERSION' """Default application version (used by ``waf dist``)""" TOP = 'top' """The variable name for the top-level directory in wscript files""" OUT = 'out' """The variable name for the output directory in wscript files""" WSCRIPT_FILE = 'wscript' """Name of the waf script files""" launch_dir = '' """Directory from which waf has been called""" run_dir = '' """Location of the wscript file to use as the entry point""" top_dir = '' """Location of the project directory (top), if the project was configured""" out_dir = '' """Location of the build directory (out), if the project was configured""" waf_dir = '' """Directory containing the waf modules""" local_repo = '' """Local repository containing additional Waf tools (plugins)""" remote_repo = 'http://waf.googlecode.com/git/' """ Remote directory containing downloadable waf tools. The missing tools can be downloaded by using:: $ waf configure --download """ remote_locs = ['waflib/extras', 'waflib/Tools'] """ Remote directories for use with :py:const:`waflib.Context.remote_repo` """ g_module = None """ Module representing the main wscript file (see :py:const:`waflib.Context.run_dir`) """ STDOUT = 1 STDERR = -1 BOTH = 0 classes = [] """ List of :py:class:`waflib.Context.Context` subclasses that can be used as waf commands. The classes are added automatically by a metaclass. """ def create_context(cmd_name, *k, **kw): """ Create a new :py:class:`waflib.Context.Context` instance corresponding to the given command. Used in particular by :py:func:`waflib.Scripting.run_command` :param cmd_name: command :type cmd_name: string :param k: arguments to give to the context class initializer :type k: list :param k: keyword arguments to give to the context class initializer :type k: dict """ global classes for x in classes: if x.cmd == cmd_name: return x(*k, **kw) ctx = Context(*k, **kw) ctx.fun = cmd_name return ctx class store_context(type): """ Metaclass for storing the command classes into the list :py:const:`waflib.Context.classes` Context classes must provide an attribute 'cmd' representing the command to execute """ def __init__(cls, name, bases, dict): super(store_context, cls).__init__(name, bases, dict) name = cls.__name__ if name == 'ctx' or name == 'Context': return try: cls.cmd except AttributeError: raise Errors.WafError('Missing command for the context class %r (cmd)' % name) if not getattr(cls, 'fun', None): cls.fun = cls.cmd global classes classes.insert(0, cls) ctx = store_context('ctx', (object,), {}) """Base class for the :py:class:`waflib.Context.Context` classes""" class Context(ctx): """ Default context for waf commands, and base class for new command contexts. Context objects are passed to top-level functions:: def foo(ctx): print(ctx.__class__.__name__) # waflib.Context.Context Subclasses must define the attribute 'cmd': :param cmd: command to execute as in ``waf cmd`` :type cmd: string :param fun: function name to execute when the command is called :type fun: string .. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext """ errors = Errors """ Shortcut to :py:mod:`waflib.Errors` provided for convenience """ tools = {} """ A cache for modules (wscript files) read by :py:meth:`Context.Context.load` """ def __init__(self, **kw): try: rd = kw['run_dir'] except KeyError: global run_dir rd = run_dir # binds the context to the nodes in use to avoid a context singleton class node_class(waflib.Node.Node): pass self.node_class = node_class self.node_class.__module__ = "waflib.Node" self.node_class.__name__ = "Nod3" self.node_class.ctx = self self.root = self.node_class('', None) self.cur_script = None self.path = self.root.find_dir(rd) self.stack_path = [] self.exec_dict = {'ctx':self, 'conf':self, 'bld':self, 'opt':self} self.logger = None def __hash__(self): """ Return a hash value for storing context objects in dicts or sets. The value is not persistent. :return: hash value :rtype: int """ return id(self) def load(self, tool_list, *k, **kw): """ Load a Waf tool as a module, and try calling the function named :py:const:`waflib.Context.Context.fun` from it. A ``tooldir`` value may be provided as a list of module paths. :type tool_list: list of string or space-separated string :param tool_list: list of Waf tools to use """ tools = Utils.to_list(tool_list) path = Utils.to_list(kw.get('tooldir', '')) for t in tools: module = load_tool(t, path) fun = getattr(module, kw.get('name', self.fun), None) if fun: fun(self) def execute(self): """ Execute the command. Redefine this method in subclasses. """ global g_module self.recurse([os.path.dirname(g_module.root_path)]) def pre_recurse(self, node): """ Method executed immediately before a folder is read by :py:meth:`waflib.Context.Context.recurse`. The node given is set as an attribute ``self.cur_script``, and as the current path ``self.path`` :param node: script :type node: :py:class:`waflib.Node.Node` """ self.stack_path.append(self.cur_script) self.cur_script = node self.path = node.parent def post_recurse(self, node): """ Restore ``self.cur_script`` and ``self.path`` right after :py:meth:`waflib.Context.Context.recurse` terminates. :param node: script :type node: :py:class:`waflib.Node.Node` """ self.cur_script = self.stack_path.pop() if self.cur_script: self.path = self.cur_script.parent def recurse(self, dirs, name=None, mandatory=True, once=True): """ Run user code from the supplied list of directories. The directories can be either absolute, or relative to the directory of the wscript file. The methods :py:meth:`waflib.Context.Context.pre_recurse` and :py:meth:`waflib.Context.Context.post_recurse` are called immediately before and after a script has been executed. :param dirs: List of directories to visit :type dirs: list of string or space-separated string :param name: Name of function to invoke from the wscript :type name: string :param mandatory: whether sub wscript files are required to exist :type mandatory: bool :param once: read the script file once for a particular context :type once: bool """ try: cache = self.recurse_cache except: cache = self.recurse_cache = {} for d in Utils.to_list(dirs): if not os.path.isabs(d): # absolute paths only d = os.path.join(self.path.abspath(), d) WSCRIPT = os.path.join(d, WSCRIPT_FILE) WSCRIPT_FUN = WSCRIPT + '_' + (name or self.fun) node = self.root.find_node(WSCRIPT_FUN) if node and (not once or node not in cache): cache[node] = True self.pre_recurse(node) try: function_code = node.read('rU') exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) finally: self.post_recurse(node) elif not node: node = self.root.find_node(WSCRIPT) tup = (node, name or self.fun) if node and (not once or tup not in cache): cache[tup] = True self.pre_recurse(node) try: wscript_module = load_module(node.abspath()) user_function = getattr(wscript_module, (name or self.fun), None) if not user_function: if not mandatory: continue raise Errors.WafError('No function %s defined in %s' % (name or self.fun, node.abspath())) user_function(self) finally: self.post_recurse(node) elif not node: if not mandatory: continue raise Errors.WafError('No wscript file in directory %s' % d) def exec_command(self, cmd, **kw): """ Execute a command and return the exit status. If the context has the attribute 'log', capture and log the process stderr/stdout for logging purposes:: def run(tsk): ret = tsk.generator.bld.exec_command('touch foo.txt') return ret Do not confuse this method with :py:meth:`waflib.Context.Context.cmd_and_log` which is used to return the standard output/error values. :param cmd: command argument for subprocess.Popen :param kw: keyword arguments for subprocess.Popen """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) Logs.debug('runner: %r' % cmd) Logs.debug('runner_env: kw=%s' % kw) try: if self.logger: # warning: may deadlock with a lot of output (subprocess limitation) self.logger.info(cmd) kw['stdout'] = kw['stderr'] = subprocess.PIPE p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() if out: self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) if err: self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) return p.returncode else: p = subprocess.Popen(cmd, **kw) return p.wait() except OSError: return -1 def cmd_and_log(self, cmd, **kw): """ Execute a command and return stdout if the execution is successful. An exception is thrown when the exit status is non-0. In that case, both stderr and stdout will be bound to the WafError object:: def configure(conf): out = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.STDOUT, quiet=waflib.Context.BOTH) (out, err) = conf.cmd_and_log(['echo', 'hello'], output=waflib.Context.BOTH) try: conf.cmd_and_log(['which', 'someapp'], output=waflib.Context.BOTH) except Exception as e: print(e.stdout, e.stderr) :param cmd: args for subprocess.Popen :param kw: keyword arguments for subprocess.Popen """ subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) Logs.debug('runner: %r' % cmd) if 'quiet' in kw: quiet = kw['quiet'] del kw['quiet'] else: quiet = None if 'output' in kw: to_ret = kw['output'] del kw['output'] else: to_ret = STDOUT kw['stdout'] = kw['stderr'] = subprocess.PIPE if quiet is None: self.to_log(cmd) try: p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() except Exception as e: raise Errors.WafError('Execution failure: %s' % str(e), ex=e) if not isinstance(out, str): out = out.decode(sys.stdout.encoding or 'iso8859-1') if not isinstance(err, str): err = err.decode(sys.stdout.encoding or 'iso8859-1') if out and quiet != STDOUT and quiet != BOTH: self.to_log('out: %s' % out) if err and quiet != STDERR and quiet != BOTH: self.to_log('err: %s' % err) if p.returncode: e = Errors.WafError('Command %r returned %r' % (cmd, p.returncode)) e.returncode = p.returncode e.stderr = err e.stdout = out raise e if to_ret == BOTH: return (out, err) elif to_ret == STDERR: return err return out def fatal(self, msg, ex=None): """ Raise a configuration error to interrupt the execution immediately:: def configure(conf): conf.fatal('a requirement is missing') :param msg: message to display :type msg: string :param ex: optional exception object :type ex: exception """ if self.logger: self.logger.info('from %s: %s' % (self.path.abspath(), msg)) try: msg = '%s\n(complete log in %s)' % (msg, self.logger.handlers[0].baseFilename) except: pass raise self.errors.ConfigurationError(msg, ex=ex) def to_log(self, msg): """ Log some information to the logger (if present), or to stderr. If the message is empty, it is not printed:: def build(bld): bld.to_log('starting the build') When in doubt, override this method, or provide a logger on the context class. :param msg: message :type msg: string """ if not msg: return if self.logger: self.logger.info(msg) else: sys.stderr.write(str(msg)) sys.stderr.flush() def msg(self, msg, result, color=None): """ Print a configuration message of the form ``msg: result``. The second part of the message will be in colors. The output can be disabled easly by setting ``in_msg`` to a positive value:: def configure(conf): self.in_msg = 1 conf.msg('Checking for library foo', 'ok') # no output :param msg: message to display to the user :type msg: string :param result: result to display :type result: string or boolean :param color: color to use, see :py:const:`waflib.Logs.colors_lst` :type color: string """ self.start_msg(msg) if not isinstance(color, str): color = result and 'GREEN' or 'YELLOW' self.end_msg(result, color) def start_msg(self, msg): """ Print the beginning of a 'Checking for xxx' message. See :py:meth:`waflib.Context.Context.msg` """ try: if self.in_msg: self.in_msg += 1 return except: self.in_msg = 0 self.in_msg += 1 try: self.line_just = max(self.line_just, len(msg)) except AttributeError: self.line_just = max(40, len(msg)) for x in (self.line_just * '-', msg): self.to_log(x) Logs.pprint('NORMAL', "%s :" % msg.ljust(self.line_just), sep='') def end_msg(self, result, color=None): """Print the end of a 'Checking for' message. See :py:meth:`waflib.Context.Context.msg`""" self.in_msg -= 1 if self.in_msg: return defcolor = 'GREEN' if result == True: msg = 'ok' elif result == False: msg = 'not found' defcolor = 'YELLOW' else: msg = str(result) self.to_log(msg) Logs.pprint(color or defcolor, msg) def load_special_tools(self, var, ban=[]): global waf_dir lst = self.root.find_node(waf_dir).find_node('waflib/extras').ant_glob(var) for x in lst: if not x.name in ban: load_tool(x.name.replace('.py', '')) cache_modules = {} """ Dictionary holding already loaded modules, keyed by their absolute path. The modules are added automatically by :py:func:`waflib.Context.load_module` """ def load_module(path): """ Load a source file as a python module. :param path: file path :type path: string :return: Loaded Python module :rtype: module """ try: return cache_modules[path] except KeyError: pass module = imp.new_module(WSCRIPT_FILE) try: code = Utils.readf(path, m='rU') except (IOError, OSError): raise Errors.WafError('Could not read the file %r' % path) module_dir = os.path.dirname(path) sys.path.insert(0, module_dir) exec(compile(code, path, 'exec'), module.__dict__) sys.path.remove(module_dir) cache_modules[path] = module return module def load_tool(tool, tooldir=None): """ Import a Waf tool (python module), and store it in the dict :py:const:`waflib.Context.Context.tools` :type tool: string :param tool: Name of the tool :type tooldir: list :param tooldir: List of directories to search for the tool module """ tool = tool.replace('++', 'xx') tool = tool.replace('java', 'javaw') tool = tool.replace('compiler_cc', 'compiler_c') if tooldir: assert isinstance(tooldir, list) sys.path = tooldir + sys.path try: __import__(tool) ret = sys.modules[tool] Context.tools[tool] = ret return ret finally: for d in tooldir: sys.path.remove(d) else: global waf_dir try: os.stat(os.path.join(waf_dir, 'waflib', 'extras', tool + '.py')) d = 'waflib.extras.%s' % tool except: try: os.stat(os.path.join(waf_dir, 'waflib', 'Tools', tool + '.py')) d = 'waflib.Tools.%s' % tool except: d = tool # user has messed with sys.path __import__(d) ret = sys.modules[d] Context.tools[tool] = ret return ret debian/waf-1.6/waflib/extras/0000775000000000000000000000000012253225220013014 5ustar debian/waf-1.6/waflib/extras/fc_open64.py0000664000000000000000000000275012145744415015171 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].insert(0, 'fc_open64') @conf def find_openf95(conf): """Find the Open64 Fortran Compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['openf95', 'openf90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_open64_version(fc) conf.env.FC_NAME = 'OPEN64' conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' @conf def openf95_flags(conf): v = conf.env v['FCFLAGS_DEBUG'] = ['-fullwarn'] @conf def openf95_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() openf95_modifier_func = getattr(conf, 'openf95_modifier_' + dest_os, None) if openf95_modifier_func: openf95_modifier_func() @conf def get_open64_version(conf, fc): """Get the Open64 compiler version""" version_re = re.compile(r"Open64 Compiler Suite: *Version *(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-version'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Open64 version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_openf95() conf.find_ar() conf.fc_flags() conf.openf95_flags() conf.openf95_modifier_platform() debian/waf-1.6/waflib/extras/msvs.py0000664000000000000000000007240012145744415014375 0ustar #! /usr/bin/env python # encoding: utf-8 # Avalanche Studios 2009-2011 # Thomas Nagy 2011 """ 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. """ """ To add this tool to your project: def options(conf): opt.load('msvs') It can be a good idea to add the sync_exec tool too. To generate solution files: $ waf configure msvs To customize the outputs, provide subclasses in your wscript files: from waflib.extras import msvs class vsnode_target(msvs.vsnode_target): def get_build_command(self, props): # likely to be required return "waf.bat build" def collect_source(self): # likely to be required ... class msvs_bar(msvs.msvs_generator): def init(self): msvs.msvs_generator.init(self) self.vsnode_target = vsnode_target The msvs class re-uses the same build() function for reading the targets (task generators), you may therefore specify msvs settings on the context object: def build(bld): bld.solution_name = 'foo.sln' bld.waf_command = 'waf.bat' bld.projects_dir = bld.srcnode.make_node('.depproj') bld.projects_dir.mkdir() For visual studio 2008, the command is called 'msvs2008', and the classes such as vsnode_target are wrapped by a decorator class 'wrap_2008' to provide special functionality. ASSUMPTIONS: * a project can be either a directory or a target, vcxproj files are written only for targets that have source files * each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path """ import os, re, sys import uuid # requires python 2.5 from waflib.Build import BuildContext from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' PROJECT_TEMPLATE = r''' ${for b in project.build_properties} ${b.configuration} ${b.platform} ${endfor} {${project.uuid}} MakeFileProj ${project.name} ${for b in project.build_properties} Makefile ${b.outdir} ${endfor} ${for b in project.build_properties} ${endfor} ${for b in project.build_properties} ${xml:project.get_build_command(b)} ${xml:project.get_rebuild_command(b)} ${xml:project.get_clean_command(b)} ${xml:b.includes_search_path} ${xml:b.preprocessor_definitions};$(NMakePreprocessorDefinitions) ${xml:b.includes_search_path} $(ExecutablePath) ${if getattr(b, 'output_file', None)} ${xml:b.output_file} ${endif} ${if getattr(b, 'deploy_dir', None)} ${xml:b.deploy_dir} ${endif} ${endfor} ${for b in project.build_properties} ${if getattr(b, 'deploy_dir', None)} CopyToHardDrive ${endif} ${endfor} ${for x in project.source} <${project.get_key(x)} Include='${x.abspath()}' /> ${endfor} ''' FILTER_TEMPLATE = ''' ${for x in project.source} <${project.get_key(x)} Include="${x.abspath()}"> ${project.get_filter_name(x.parent)} ${endfor} ${for x in project.dirs()} {${project.make_uuid(x.abspath())}} ${endfor} ''' PROJECT_2008_TEMPLATE = r''' ${if project.build_properties} ${for b in project.build_properties} ${endfor} ${else} ${endif} ${if project.build_properties} ${for b in project.build_properties} ${endfor} ${else} ${endif} ${project.display_filter()} ''' SOLUTION_TEMPLATE = '''Microsoft Visual Studio Solution File, Format Version ${project.numver} # Visual Studio ${project.vsver} ${for p in project.all_projects} Project("{${p.ptype()}}") = "${p.name}", "${p.title}", "{${p.uuid}}" EndProject${endfor} Global GlobalSection(SolutionConfigurationPlatforms) = preSolution ${if project.all_projects} ${for (configuration, platform) in project.all_projects[0].ctx.project_configurations()} ${configuration}|${platform} = ${configuration}|${platform} ${endfor} ${endif} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution ${for p in project.all_projects} ${if hasattr(p, 'source')} ${for b in p.build_properties} {${p.uuid}}.${b.configuration}|${b.platform}.ActiveCfg = ${b.configuration}|${b.platform} ${if getattr(p, 'is_active', None)} {${p.uuid}}.${b.configuration}|${b.platform}.Build.0 = ${b.configuration}|${b.platform} ${endif} ${endfor} ${endif} ${endfor} EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution ${for p in project.all_projects} ${if p.parent} {${p.uuid}} = {${p.parent.uuid}} ${endif} ${endfor} EndGlobalSection EndGlobal ''' COMPILE_TEMPLATE = '''def f(project): lst = [] def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") %s #f = open('cmd.txt', 'w') #f.write(str(lst)) #f.close() return ''.join(lst) ''' reg_act = re.compile(r"(?P\\)|(?P\$\$)|(?P\$\{(?P[^}]*?)\})", re.M) def compile_template(line): """ Compile a template expression into a python function (like jsps, but way shorter) """ extr = [] def repl(match): g = match.group if g('dollar'): return "$" elif g('backslash'): return "\\" elif g('subst'): extr.append(g('code')) return "<<|@|>>" return None line2 = reg_act.sub(repl, line) params = line2.split('<<|@|>>') assert(extr) indent = 0 buf = [] dvars = [] app = buf.append def app(txt): buf.append(indent * '\t' + txt) for x in range(len(extr)): if params[x]: app("lst.append(%r)" % params[x]) f = extr[x] if f.startswith('if') or f.startswith('for'): app(f + ':') indent += 1 elif f.startswith('py:'): app(f[3:]) elif f.startswith('endif') or f.startswith('endfor'): indent -= 1 elif f.startswith('else') or f.startswith('elif'): indent -= 1 app(f + ':') indent += 1 elif f.startswith('xml:'): app('lst.append(xml_escape(%s))' % f[4:]) else: #app('lst.append((%s) or "cannot find %s")' % (f, f)) app('lst.append(%s)' % f) if extr: if params[-1]: app("lst.append(%r)" % params[-1]) fun = COMPILE_TEMPLATE % "\n\t".join(buf) #print(fun) return Task.funex(fun) re_blank = re.compile('(\n|\r|\\s)*\n', re.M) def rm_blank_lines(txt): txt = re_blank.sub('\r\n', txt) return txt BOM = '\xef\xbb\xbf' try: BOM = bytes(BOM, 'iso8859-1') # python 3 except: pass def stealth_write(self, data, flags='wb'): try: x = unicode except: data = data.encode('utf-8') # python 3 else: data = data.decode(sys.getfilesystemencoding(), 'replace') data = data.encode('utf-8') if self.name.endswith('.vcproj') or self.name.endswith('.vcxproj'): data = BOM + data try: txt = self.read(flags='rb') if txt != data: raise ValueError('must write') except (IOError, ValueError): self.write(data, flags=flags) else: Logs.debug('msvs: skipping %s' % self.abspath()) Node.Node.stealth_write = stealth_write re_quote = re.compile("[^a-zA-Z0-9-]") def quote(s): return re_quote.sub("_", s) def xml_escape(value): return value.replace("&", "&").replace('"', """).replace("'", "'").replace("<", "<").replace(">", ">") def make_uuid(v, prefix = None): """ simple utility function """ if isinstance(v, dict): keys = list(v.keys()) keys.sort() tmp = str([(k, v[k]) for k in keys]) else: tmp = str(v) d = Utils.md5(tmp.encode()).hexdigest().upper() if prefix: d = '%s%s' % (prefix, d[8:]) gid = uuid.UUID(d, version = 4) return str(gid).upper() def diff(node, fromnode): # difference between two nodes, but with "(..)" instead of ".." c1 = node c2 = fromnode c1h = c1.height() c2h = c2.height() lst = [] up = 0 while c1h > c2h: lst.append(c1.name) c1 = c1.parent c1h -= 1 while c2h > c1h: up += 1 c2 = c2.parent c2h -= 1 while id(c1) != id(c2): lst.append(c1.name) up += 1 c1 = c1.parent c2 = c2.parent for i in range(up): lst.append('(..)') lst.reverse() return tuple(lst) class build_property(object): pass class vsnode(object): """ Abstract class representing visual studio elements We assume that all visual studio nodes have a uuid and a parent """ def __init__(self, ctx): self.ctx = ctx # msvs context self.name = '' # string, mandatory self.vspath = '' # path in visual studio (name for dirs, absolute path for projects) self.uuid = '' # string, mandatory self.parent = None # parent node for visual studio nesting def get_waf(self): """ Override in subclasses... """ return 'cd /d "%s" & %s' % (self.ctx.srcnode.abspath(), getattr(self.ctx, 'waf_command', 'waf.bat')) def ptype(self): """ Return a special uuid for projects written in the solution file """ pass def write(self): """ Write the project file, by default, do nothing """ pass def make_uuid(self, val): """ Alias for creating uuid values easily (the templates cannot access global variables) """ return make_uuid(val) class vsnode_vsdir(vsnode): """ Nodes representing visual studio folders (which do not match the filesystem tree!) """ VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8" def __init__(self, ctx, uuid, name, vspath=''): vsnode.__init__(self, ctx) self.title = self.name = name self.uuid = uuid self.vspath = vspath or name def ptype(self): return self.VS_GUID_SOLUTIONFOLDER class vsnode_project(vsnode): """ Abstract class representing visual studio project elements A project is assumed to be writable, and has a node representing the file to write to """ VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942" def ptype(self): return self.VS_GUID_VCPROJ def __init__(self, ctx, node): vsnode.__init__(self, ctx) self.path = node self.uuid = make_uuid(node.abspath()) self.name = node.name self.title = self.path.abspath() self.source = [] # list of node objects self.build_properties = [] # list of properties (nmake commands, output dir, etc) def dirs(self): """ Get the list of parent folders of the source files (header files included) for writing the filters """ lst = [] def add(x): if x.height() > self.tg.path.height() and x not in lst: lst.append(x) add(x.parent) for x in self.source: add(x.parent) return lst def write(self): Logs.debug('msvs: creating %r' % self.path) # first write the project file template1 = compile_template(PROJECT_TEMPLATE) proj_str = template1(self) proj_str = rm_blank_lines(proj_str) self.path.stealth_write(proj_str) # then write the filter template2 = compile_template(FILTER_TEMPLATE) filter_str = template2(self) filter_str = rm_blank_lines(filter_str) tmp = self.path.parent.make_node(self.path.name + '.filters') tmp.stealth_write(filter_str) def get_key(self, node): """ required for writing the source files """ name = node.name if name.endswith('.cpp') or name.endswith('.c'): return 'ClCompile' return 'ClInclude' def collect_properties(self): """ Returns a list of triplet (configuration, platform, output_directory) """ ret = [] for c in self.ctx.configurations: for p in self.ctx.platforms: x = build_property() x.outdir = '' x.configuration = c x.platform = p x.preprocessor_definitions = '' x.includes_search_path = '' # can specify "deploy_dir" too ret.append(x) self.build_properties = ret def get_build_params(self, props): opt = '--execsolution=%s' % self.ctx.get_solution_node().abspath() return (self.get_waf(), opt) def get_build_command(self, props): return "%s build %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build %s" % self.get_build_params(props) def get_filter_name(self, node): lst = diff(node, self.tg.path) return '\\'.join(lst) or '.' class vsnode_alias(vsnode_project): def __init__(self, ctx, node, name): vsnode_project.__init__(self, ctx, node) self.name = name self.output_file = '' class vsnode_build_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make all" (starting one process by target is slow) This is the only alias enabled by default """ def __init__(self, ctx, node, name='build_all_projects'): vsnode_alias.__init__(self, ctx, node, name) self.is_active = True class vsnode_install_all(vsnode_alias): """ Fake target used to emulate the behaviour of "make install" """ def __init__(self, ctx, node, name='install_all_projects'): vsnode_alias.__init__(self, ctx, node, name) def get_build_command(self, props): return "%s build install %s" % self.get_build_params(props) def get_clean_command(self, props): return "%s clean %s" % self.get_build_params(props) def get_rebuild_command(self, props): return "%s clean build install %s" % self.get_build_params(props) class vsnode_project_view(vsnode_alias): """ Fake target used to emulate a file system view """ def __init__(self, ctx, node, name='project_view'): vsnode_alias.__init__(self, ctx, node, name) self.tg = self.ctx() # fake one, cannot remove self.exclude_files = Node.exclude_regs + ''' waf-1.6.* waf3-1.6.*/** .waf-1.6.* .waf3-1.6.*/** **/*.sdf **/*.suo **/*.ncb **/%s ''' % Options.lockfile def collect_source(self): # this is likely to be slow self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files) def get_build_command(self, props): params = self.get_build_params(props) + (self.ctx.cmd,) return "%s %s %s" % params def get_clean_command(self, props): return "" def get_rebuild_command(self, props): return self.get_build_command(props) class vsnode_target(vsnode_project): """ Visual studio project representing a targets (programs, libraries, etc) and bound to a task generator """ def __init__(self, ctx, tg): """ A project is more or less equivalent to a file/folder """ base = getattr(ctx, 'projects_dir', None) or tg.path node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node vsnode_project.__init__(self, ctx, node) self.name = quote(tg.name) self.tg = tg # task generator def get_build_params(self, props): """ Override the default to add the target name """ opt = '--execsolution=%s' % self.ctx.get_solution_node().abspath() if getattr(self, 'tg', None): opt += " --targets=%s" % self.tg.name return (self.get_waf(), opt) def collect_source(self): tg = self.tg source_files = tg.to_nodes(getattr(tg, 'source', [])) include_dirs = Utils.to_list(getattr(tg, 'msvs_includes', [])) include_files = [] for x in include_dirs: if isinstance(x, str): x = tg.path.find_node(x) if x: lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)] include_files.extend(lst) # remove duplicates self.source.extend(list(set(source_files + include_files))) self.source.sort(key=lambda x: x.abspath()) def collect_properties(self): """ Visual studio projects are associated with platforms and configurations (for building especially) """ super(vsnode_target, self).collect_properties() for x in self.build_properties: x.outdir = self.path.parent.abspath() x.preprocessor_definitions = '' x.includes_search_path = '' try: tsk = self.tg.link_task except AttributeError: pass else: x.output_file = tsk.outputs[0].abspath() x.preprocessor_definitions = ';'.join(tsk.env.DEFINES) x.includes_search_path = ';'.join(self.tg.env.INCPATHS) class msvs_generator(BuildContext): '''generates a visual studio 2010 solution''' cmd = 'msvs' fun = 'build' def init(self): """ Some data that needs to be present """ if not getattr(self, 'configurations', None): self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc if not getattr(self, 'platforms', None): self.platforms = ['Win32'] if not getattr(self, 'all_projects', None): self.all_projects = [] if not getattr(self, 'project_extension', None): self.project_extension = '.vcxproj' if not getattr(self, 'projects_dir', None): self.projects_dir = self.srcnode.make_node('.depproj') self.projects_dir.mkdir() # bind the classes to the object, so that subclass can provide custom generators if not getattr(self, 'vsnode_vsdir', None): self.vsnode_vsdir = vsnode_vsdir if not getattr(self, 'vsnode_target', None): self.vsnode_target = vsnode_target if not getattr(self, 'vsnode_build_all', None): self.vsnode_build_all = vsnode_build_all if not getattr(self, 'vsnode_install_all', None): self.vsnode_install_all = vsnode_install_all if not getattr(self, 'vsnode_project_view', None): self.vsnode_project_view = vsnode_project_view self.numver = '11.00' self.vsver = '2010' def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) # user initialization self.init() # two phases for creating the solution self.collect_projects() # add project objects into "self.all_projects" self.write_files() # write the corresponding project and solution files def collect_projects(self): """ Fill the list self.all_projects with project objects Fill the list of build targets """ self.collect_targets() self.add_aliases() self.collect_dirs() self.all_projects.sort(key=lambda x: getattr(x, 'path', None) and x.path.abspath() or x.name) def write_files(self): """ Write the project and solution files from the data collected so far. It is unlikely that you will want to change this """ for p in self.all_projects: p.write() # and finally write the solution file node = self.get_solution_node() node.parent.mkdir() Logs.warn('Creating %r' % node) template1 = compile_template(SOLUTION_TEMPLATE) sln_str = template1(self) sln_str = rm_blank_lines(sln_str) node.stealth_write(sln_str) def get_solution_node(self): """ The solution filename is required when writing the .vcproj files return self.solution_node and if it does not exist, make one """ try: return self.solution_node except: pass solution_name = getattr(self, 'solution_name', None) if not solution_name: solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.sln' if os.path.isabs(solution_name): self.solution_node = self.root.make_node(solution_name) else: self.solution_node = self.srcnode.make_node(solution_name) return self.solution_node def project_configurations(self): """ Helper that returns all the pairs (config,platform) """ ret = [] for c in self.configurations: for p in self.platforms: ret.append((c, p)) return ret def collect_targets(self): """ Process the list of task generators """ for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue if not hasattr(tg, 'msvs_includes'): tg.msvs_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', [])) tg.post() if not getattr(tg, 'link_task', None): continue p = self.vsnode_target(self, tg) p.collect_source() # delegate this processing p.collect_properties() self.all_projects.append(p) def add_aliases(self): """ Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7 We also add an alias for "make install" (disabled by default) """ base = getattr(self, 'projects_dir', None) or self.tg.path node_project = base.make_node('build_all_projects' + self.project_extension) # Node p_build = self.vsnode_build_all(self, node_project) p_build.collect_properties() self.all_projects.append(p_build) node_project = base.make_node('install_all_projects' + self.project_extension) # Node p_install = self.vsnode_install_all(self, node_project) p_install.collect_properties() self.all_projects.append(p_install) node_project = base.make_node('project_view' + self.project_extension) # Node p_view = self.vsnode_project_view(self, node_project) p_view.collect_source() p_view.collect_properties() self.all_projects.append(p_view) n = self.vsnode_vsdir(self, make_uuid(self.srcnode.abspath() + 'build_aliases'), "build_aliases") p_build.parent = p_install.parent = p_view.parent = n self.all_projects.append(n) def collect_dirs(self): """ Create the folder structure in the Visual studio project view """ seen = {} def make_parents(proj): # look at a project, try to make a parent if getattr(proj, 'parent', None): # aliases already have parents return x = proj.iter_path if x in seen: proj.parent = seen[x] return # There is not vsnode_vsdir for x. # So create a project representing the folder "x" n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.abspath()), x.name) n.iter_path = x.parent self.all_projects.append(n) # recurse up to the project directory if x.height() > self.srcnode.height() + 1: make_parents(n) for p in self.all_projects[:]: # iterate over a copy of all projects if not getattr(p, 'tg', None): # but only projects that have a task generator continue # make a folder for each task generator p.iter_path = p.tg.path make_parents(p) def wrap_2008(cls): class dec(cls): def __init__(self, *k, **kw): cls.__init__(self, *k, **kw) self.project_template = PROJECT_2008_TEMPLATE def display_filter(self): root = build_property() root.subfilters = [] root.sourcefiles = [] root.source = [] root.name = '' @Utils.run_once def add_path(lst): if not lst: return root child = build_property() child.subfilters = [] child.sourcefiles = [] child.source = [] child.name = lst[-1] par = add_path(lst[:-1]) par.subfilters.append(child) return child for x in self.source: # this crap is for enabling subclasses to override get_filter_name tmp = self.get_filter_name(x.parent) tmp = tmp != '.' and tuple(tmp.split('\\')) or () par = add_path(tmp) par.source.append(x) def display(n): buf = [] for x in n.source: buf.append('\n' % (xml_escape(x.abspath()), self.get_key(x))) for x in n.subfilters: buf.append('' % xml_escape(x.name)) buf.append(display(x)) buf.append('') return '\n'.join(buf) return display(root) def get_key(self, node): """ If you do not want to let visual studio use the default file extensions, override this method to return a value: 0: C/C++ Code, 1: C++ Class, 2: C++ Header File, 3: C++ Form, 4: C++ Control, 5: Text File, 6: DEF File, 7: IDL File, 8: Makefile, 9: RGS File, 10: RC File, 11: RES File, 12: XSD File, 13: XML File, 14: HTML File, 15: CSS File, 16: Bitmap, 17: Icon, 18: Resx File, 19: BSC File, 20: XSX File, 21: C++ Web Service, 22: ASAX File, 23: Asp Page, 24: Document, 25: Discovery File, 26: C# File, 27: eFileTypeClassDiagram, 28: MHTML Document, 29: Property Sheet, 30: Cursor, 31: Manifest, 32: eFileTypeRDLC """ return '' def write(self): Logs.debug('msvs: creating %r' % self.path) template1 = compile_template(self.project_template) proj_str = template1(self) proj_str = rm_blank_lines(proj_str) self.path.stealth_write(proj_str) return dec class msvs_2008_generator(msvs_generator): '''generates a visual studio 2008 solution''' cmd = 'msvs2008' fun = msvs_generator.fun def init(self): if not getattr(self, 'project_extension', None): self.project_extension = '_2008.vcproj' if not getattr(self, 'solution_name', None): self.solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '_2008.sln' if not getattr(self, 'vsnode_target', None): self.vsnode_target = wrap_2008(vsnode_target) if not getattr(self, 'vsnode_build_all', None): self.vsnode_build_all = wrap_2008(vsnode_build_all) if not getattr(self, 'vsnode_install_all', None): self.vsnode_install_all = wrap_2008(vsnode_install_all) if not getattr(self, 'vsnode_project_view', None): self.vsnode_project_view = wrap_2008(vsnode_project_view) msvs_generator.init(self) self.numver = '10.00' self.vsver = '2008' def options(ctx): """ If the msvs option is used, try to detect if the build is made from visual studio """ ctx.add_option('--execsolution', action='store', help='when building with visual studio, use a build state file') old = BuildContext.execute def override_build_state(ctx): def lock(rm, add): uns = ctx.options.execsolution.replace('.sln', rm) uns = ctx.root.make_node(uns) try: uns.delete() except: pass uns = ctx.options.execsolution.replace('.sln', add) uns = ctx.root.make_node(uns) try: uns.write('') except: pass if ctx.options.execsolution: ctx.launch_dir = Context.top_dir # force a build for the whole project (invalid cwd when called by visual studio) lock('.lastbuildstate', '.unsuccessfulbuild') old(ctx) lock('.unsuccessfulbuild', '.lastbuildstate') else: old(ctx) BuildContext.execute = override_build_state debian/waf-1.6/waflib/extras/parallel_debug.py0000664000000000000000000002233412145744415016350 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2007-2010 (ita) """ Debugging helper for parallel compilation, outputs a file named pdebug.svg in the source directory:: def options(opt): opt.load('parallel_debug') def configure(conf): conf.load('parallel_debug') def build(bld): ... """ import os, time, sys try: from Queue import Queue except: from queue import Queue from waflib import Runner, Options, Utils, Task, Logs, Errors #import random #random.seed(100) def options(opt): opt.add_option('--dtitle', action='store', default='Parallel build representation for %r' % ' '.join(sys.argv), help='title for the svg diagram', dest='dtitle') opt.add_option('--dwidth', action='store', type='int', help='diagram width', default=800, dest='dwidth') opt.add_option('--dtime', action='store', type='float', help='recording interval in seconds', default=0.009, dest='dtime') opt.add_option('--dband', action='store', type='int', help='band width', default=22, dest='dband') opt.add_option('--dmaxtime', action='store', type='float', help='maximum time, for drawing fair comparisons', default=0, dest='dmaxtime') # red #ff4d4d # green #4da74d # lila #a751ff color2code = { 'GREEN' : '#4da74d', 'YELLOW' : '#fefe44', 'PINK' : '#a751ff', 'RED' : '#cc1d1d', 'BLUE' : '#6687bb', 'CYAN' : '#34e2e2', } mp = {} info = [] # list of (text,color) def map_to_color(name): if name in mp: return mp[name] try: cls = Task.classes[name] except KeyError: return color2code['RED'] if cls.color in mp: return mp[cls.color] if cls.color in color2code: return color2code[cls.color] return color2code['RED'] def process(self): m = self.master if m.stop: m.out.put(self) return self.master.set_running(1, id(Utils.threading.currentThread()), self) # remove the task signature immediately before it is executed # in case of failure the task will be executed again try: del self.generator.bld.task_sigs[self.uid()] except: pass try: self.generator.bld.returned_tasks.append(self) self.log_display(self.generator.bld) ret = self.run() except Exception: self.err_msg = Utils.ex_stack() self.hasrun = Task.EXCEPTION # TODO cleanup m.error_handler(self) m.out.put(self) return if ret: self.err_code = ret self.hasrun = Task.CRASHED else: try: self.post_run() except Errors.WafError: pass except Exception: self.err_msg = Utils.ex_stack() self.hasrun = Task.EXCEPTION else: self.hasrun = Task.SUCCESS if self.hasrun != Task.SUCCESS: m.error_handler(self) self.master.set_running(-1, id(Utils.threading.currentThread()), self) m.out.put(self) Task.TaskBase.process_back = Task.TaskBase.process Task.TaskBase.process = process old_start = Runner.Parallel.start def do_start(self): try: Options.options.dband except AttributeError: self.bld.fatal('use def options(opt): opt.load("parallel_debug")!') self.taskinfo = Queue() old_start(self) if self.dirty: process_colors(self) Runner.Parallel.start = do_start def set_running(self, by, i, tsk): self.taskinfo.put( (i, id(tsk), time.time(), tsk.__class__.__name__, self.processed, self.count, by) ) Runner.Parallel.set_running = set_running def name2class(name): return name.replace(' ', '_').replace('.', '_') def process_colors(producer): # first, cast the parameters tmp = [] try: while True: tup = producer.taskinfo.get(False) tmp.append(list(tup)) except: pass try: ini = float(tmp[0][2]) except: return if not info: seen = [] for x in tmp: name = x[3] if not name in seen: seen.append(name) else: continue info.append((name, map_to_color(name))) info.sort(key=lambda x: x[0]) thread_count = 0 acc = [] for x in tmp: thread_count += x[6] acc.append("%d %d %f %r %d %d %d" % (x[0], x[1], x[2] - ini, x[3], x[4], x[5], thread_count)) data_node = producer.bld.path.make_node('pdebug.dat') data_node.write('\n'.join(acc)) tmp = [lst[:2] + [float(lst[2]) - ini] + lst[3:] for lst in tmp] st = {} for l in tmp: if not l[0] in st: st[l[0]] = len(st.keys()) tmp = [ [st[lst[0]]] + lst[1:] for lst in tmp ] THREAD_AMOUNT = len(st.keys()) st = {} for l in tmp: if not l[1] in st: st[l[1]] = len(st.keys()) tmp = [ [lst[0]] + [st[lst[1]]] + lst[2:] for lst in tmp ] BAND = Options.options.dband seen = {} acc = [] for x in range(len(tmp)): line = tmp[x] id = line[1] if id in seen: continue seen[id] = True begin = line[2] thread_id = line[0] for y in range(x + 1, len(tmp)): line = tmp[y] if line[1] == id: end = line[2] #print id, thread_id, begin, end #acc.append( ( 10*thread_id, 10*(thread_id+1), 10*begin, 10*end ) ) acc.append( (BAND * begin, BAND*thread_id, BAND*end - BAND*begin, BAND, line[3]) ) break if Options.options.dmaxtime < 0.1: gwidth = 1 for x in tmp: m = BAND * x[2] if m > gwidth: gwidth = m else: gwidth = BAND * Options.options.dmaxtime ratio = float(Options.options.dwidth) / gwidth gwidth = Options.options.dwidth gheight = BAND * (THREAD_AMOUNT + len(info) + 1.5) out = [] out.append(""" \n """ % (0, 0, gwidth + 4, gheight + 4, 0, 0, gwidth + 4, gheight + 4)) # main title if Options.options.dtitle: out.append("""%s """ % (gwidth/2, gheight - 5, Options.options.dtitle)) # the rectangles groups = {} for (x, y, w, h, clsname) in acc: try: groups[clsname].append((x, y, w, h)) except: groups[clsname] = [(x, y, w, h)] for cls in groups: out.append("\n" % name2class(cls)) for (x, y, w, h) in groups[cls]: out.append("""\n""" % (2 + x*ratio, 2 + y, w*ratio, h, map_to_color(cls))) out.append("\n") # output the caption cnt = THREAD_AMOUNT for (text, color) in info: # caption box b = BAND/2 out.append("""\n""" % (name2class(text), 2 + BAND, 5 + (cnt + 0.5) * BAND, b, b, color)) # caption text out.append("""%s\n""" % (2 + 2 * BAND, 5 + (cnt + 0.5) * BAND + 10, text)) cnt += 1 out.append(""" """) out.append("\n") node = producer.bld.path.make_node('pdebug.svg') node.write("".join(out)) Logs.warn('Created the diagram %r' % node.abspath()) p = node.parent.abspath() producer.bld.exec_command(['convert', p + os.sep + 'pdebug.svg', p + os.sep + 'pdebug.png']) debian/waf-1.6/waflib/extras/fc_xlf.py0000664000000000000000000000301212145744415014637 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['aix'].insert(0, 'fc_xlf') @conf def find_xlf(conf): """Find the xlf program (will look in the environment variable 'FC')""" fc = conf.find_program(['xlf2003_r', 'xlf2003', 'xlf95_r', 'xlf95', 'xlf90_r', 'xlf90', 'xlf_r', 'xlf'], var='FC') fc = conf.cmd_to_list(fc) conf.get_xlf_version(fc) conf.env.FC_NAME='XLF' @conf def xlf_flags(conf): v = conf.env v['FCDEFINES_ST'] = '-WF,-D%s' v['FCFLAGS_fcshlib'] = ['-qpic=small'] v['FCFLAGS_DEBUG'] = ['-qhalt=w'] v['LINKFLAGS_fcshlib'] = ['-Wl,-shared'] @conf def xlf_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() xlf_modifier_func = getattr(conf, 'xlf_modifier_' + dest_os, None) if xlf_modifier_func: xlf_modifier_func() @conf def get_xlf_version(conf, fc): """Get the compiler version""" version_re = re.compile(r"IBM XL Fortran.*, V(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-qversion'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the XLF version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_xlf() conf.find_ar() conf.fc_flags() conf.xlf_flags() conf.xlf_modifier_platform() debian/waf-1.6/waflib/extras/why.py0000664000000000000000000000333312145744415014213 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ This tool modifies the task signature scheme to store and obtain information about the task execution (why it must run, etc):: def configure(conf): conf.load('why') After adding the tool, a full rebuild is necessary. """ from waflib import Task, Utils, Logs, Errors def signature(self): # compute the result one time, and suppose the scan_signature will give the good result try: return self.cache_sig except AttributeError: pass self.m = Utils.md5() self.m.update(self.hcode.encode()) id_sig = self.m.digest() # explicit deps self.sig_explicit_deps() exp_sig = self.m.digest() # env vars self.sig_vars() var_sig = self.m.digest() # implicit deps / scanner results if self.scan: try: self.sig_implicit_deps() except Errors.TaskRescan: return self.signature() ret = self.cache_sig = self.m.digest() + id_sig + exp_sig + var_sig return ret Task.Task.signature = signature old = Task.Task.runnable_status def runnable_status(self): ret = old(self) if ret == Task.RUN_ME: try: old_sigs = self.generator.bld.task_sigs[self.uid()] except: Logs.debug("task: task must run as no previous signature exists") else: new_sigs = self.cache_sig def v(x): return Utils.to_hex(x) Logs.debug("Task %r" % self) msgs = ['Task must run', '* Task code', '* Source file or manual dependency', '* Configuration data variable'] tmp = 'task: -> %s: %s %s' for x in range(len(msgs)): l = len(Utils.SIG_NIL) a = new_sigs[x*l : (x+1)*l] b = old_sigs[x*l : (x+1)*l] if (a != b): Logs.debug(tmp % (msgs[x].ljust(35), v(a), v(b))) if x > 0: break return ret Task.Task.runnable_status = runnable_status debian/waf-1.6/waflib/extras/pep8.py0000664000000000000000000000663612145744415014271 0ustar #! /usr/bin/env python # encoding: utf-8 # # written by Sylvain Rouquette, 2011 ''' Install pep8 module: $ easy_install pep8 or $ pip install pep8 To add the boost tool to the waf file: $ ./waf-light --tools=compat15,pep8 or, if you have waf >= 1.6.2 $ ./waf update --files=pep8 Then add this to your wscript: [at]extension('.py', 'wscript') def run_pep8(self, node): self.create_task('Pep8', node) ''' import threading from waflib import TaskGen, Task, Options pep8 = __import__('pep8') class Pep8(Task.Task): color = 'PINK' lock = threading.Lock() def check_options(self): if pep8.options: return pep8.options = Options.options pep8.options.prog = 'pep8' excl = pep8.options.exclude.split(',') pep8.options.exclude = [s.rstrip('/') for s in excl] if pep8.options.filename: pep8.options.filename = pep8.options.filename.split(',') if pep8.options.select: pep8.options.select = pep8.options.select.split(',') else: pep8.options.select = [] if pep8.options.ignore: pep8.options.ignore = pep8.options.ignore.split(',') elif pep8.options.select: # Ignore all checks which are not explicitly selected pep8.options.ignore = [''] elif pep8.options.testsuite or pep8.options.doctest: # For doctest and testsuite, all checks are required pep8.options.ignore = [] else: # The default choice: ignore controversial checks pep8.options.ignore = pep8.DEFAULT_IGNORE.split(',') pep8.options.physical_checks = pep8.find_checks('physical_line') pep8.options.logical_checks = pep8.find_checks('logical_line') pep8.options.counters = dict.fromkeys(pep8.BENCHMARK_KEYS, 0) pep8.options.messages = {} def run(self): with Pep8.lock: self.check_options() pep8.input_file(self.inputs[0].abspath()) return 0 if not pep8.get_count() else -1 def options(opt): opt.add_option('-q', '--quiet', default=0, action='count', help="report only file names, or nothing with -qq") opt.add_option('-r', '--repeat', action='store_true', help="show all occurrences of the same error") opt.add_option('--exclude', metavar='patterns', default=pep8.DEFAULT_EXCLUDE, help="exclude files or directories which match these " "comma separated patterns (default: %s)" % pep8.DEFAULT_EXCLUDE, dest='exclude') opt.add_option('--filename', metavar='patterns', default='*.py', help="when parsing directories, only check filenames " "matching these comma separated patterns (default: " "*.py)") opt.add_option('--select', metavar='errors', default='', help="select errors and warnings (e.g. E,W6)") opt.add_option('--ignore', metavar='errors', default='', help="skip errors and warnings (e.g. E4,W)") opt.add_option('--show-source', action='store_true', help="show source code for each error") opt.add_option('--show-pep8', action='store_true', help="show text of PEP 8 for each error") opt.add_option('--statistics', action='store_true', help="count errors and warnings") opt.add_option('--count', action='store_true', help="print total number of errors and warnings " "to standard error and set exit code to 1 if " "total is not null") opt.add_option('--benchmark', action='store_true', help="measure processing speed") opt.add_option('--testsuite', metavar='dir', help="run regression tests from dir") opt.add_option('--doctest', action='store_true', help="run doctest on myself") debian/waf-1.6/waflib/extras/fc_cray.py0000664000000000000000000000267612145744415015023 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_cray') @conf def find_crayftn(conf): """Find the Cray fortran compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['crayftn'], var='FC') fc = conf.cmd_to_list(fc) conf.get_crayftn_version(fc) conf.env.FC_NAME = 'CRAY' conf.env.FC_MOD_CAPITALIZATION = 'UPPER.mod' @conf def crayftn_flags(conf): v = conf.env v['_FCMODOUTFLAGS'] = ['-em', '-J.'] # enable module files and put them in the current directoy v['FCFLAGS_DEBUG'] = ['-m1'] # more verbose compiler warnings v['FCFLAGS_fcshlib'] = ['-h pic'] v['LINKFLAGS_fcshlib'] = ['-h shared'] v['FCSTLIB_MARKER'] = '-h static' v['FCSHLIB_MARKER'] = '-h dynamic' @conf def get_crayftn_version(conf, fc): version_re = re.compile(r"Cray Fortran\s*:\s*Version\s*(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-V'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Cray Fortran compiler version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_crayftn() conf.find_ar() conf.fc_flags() conf.crayftn_flags() debian/waf-1.6/waflib/extras/add_objects.py0000664000000000000000000000030012145744415015634 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) from waflib import Logs Logs.warn('This tool has been merged to the main library, remove the references to "add_objects"') debian/waf-1.6/waflib/extras/local_rpath.py0000664000000000000000000000103212145744415015666 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) from waflib.TaskGen import after_method, feature @after_method('propagate_uselib_vars') @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') def add_rpath_stuff(self): all = self.to_list(getattr(self, 'use', [])) while all: name = all.pop() try: tg = self.bld.get_tgen_by_name(name) except: continue self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) all.extend(self.to_list(getattr(tg, 'use', []))) debian/waf-1.6/waflib/extras/make.py0000664000000000000000000000631712145744415014326 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ A make-like way of executing the build, following the relationships between inputs/outputs This algorithm will lead to slower builds, will not be as flexible as "waf build", but it might be useful for building data files (?) It is likely to break in the following cases: - files are created dynamically (no inputs or outputs) - headers - building two files from different groups """ import re from waflib import Options, Task, Logs from waflib.Build import BuildContext class MakeContext(BuildContext): '''executes tasks in a step-by-step manner, following dependencies between inputs/outputs''' cmd = 'make' fun = 'build' def __init__(self, **kw): super(MakeContext, self).__init__(**kw) self.files = Options.options.files def get_build_iterator(self): if not self.files: while 1: yield super(MakeContext, self).get_build_iterator() for g in self.groups: for tg in g: try: f = tg.post except AttributeError: pass else: f() provides = {} uses = {} all_tasks = [] tasks = [] for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: if isinstance(tg, Task.TaskBase): lst = [tg] else: lst = tg.tasks for tsk in lst: all_tasks.append(tsk) do_exec = False for node in getattr(tsk, 'inputs', []): try: uses[node].append(tsk) except: uses[node] = [tsk] if matcher(node, output=False): do_exec = True break for node in getattr(tsk, 'outputs', []): try: provides[node].append(tsk) except: provides[node] = [tsk] if matcher(node, output=True): do_exec = True break if do_exec: tasks.append(tsk) # so we have the tasks that we need to process, the list of all tasks, # the map of the tasks providing nodes, and the map of tasks using nodes if not tasks: # if there are no tasks matching, return everything in the current group result = all_tasks else: # this is like a big filter... result = set([]) seen = set([]) cur = set(tasks) while cur: result |= cur tosee = set([]) for tsk in cur: for node in getattr(tsk, 'inputs', []): if node in seen: continue seen.add(node) tosee |= set(provides.get(node, [])) cur = tosee result = list(result) Task.set_file_constraints(result) Task.set_precedence_constraints(result) yield result while 1: yield [] def get_matcher(self, pat): # this returns a function inn = True out = True if pat.startswith('in:'): out = False pat = pat.replace('in:', '') elif pat.startswith('out:'): inn = False pat = pat.replace('out:', '') anode = self.root.find_node(pat) pattern = None if not anode: if not pat.startswith('^'): pat = '^.+?%s' % pat if not pat.endswith('$'): pat = '%s$' % pat pattern = re.compile(pat) def match(node, output): if output == True and not out: return False if output == False and not inn: return False if anode: return anode == node else: return pattern.match(node.abspath()) return match debian/waf-1.6/waflib/extras/bjam.py0000664000000000000000000000754612145744415014327 0ustar #! /usr/bin/env python # per rosengren 2011 from waflib.Logs import error,warn,info,debug from waflib.TaskGen import feature, after_method from waflib.Task import Task, always_run from os import sep, readlink from os.path import abspath def options(opt): grp = opt.add_option_group('Bjam Options') grp.add_option('--bjam_src', default=None, help='You can find it in /tools/jam/src') grp.add_option('--bjam_uname', default='linuxx86_64', help='bjam is built in /bin./bjam') grp.add_option('--bjam_config', default=None) grp.add_option('--bjam_toolset', default=None) def configure(cnf): if not cnf.env.BJAM_SRC: cnf.env.BJAM_SRC = cnf.options.bjam_src if not cnf.env.BJAM_UNAME: cnf.env.BJAM_UNAME = cnf.options.bjam_uname try: cnf.find_program('bjam', path_list=[ cnf.env.BJAM_SRC + sep + 'bin.' + cnf.env.BJAM_UNAME ]) except Exception as e: cnf.env.BJAM = None if not cnf.env.BJAM_CONFIG: cnf.env.BJAM_CONFIG = cnf.options.bjam_config if not cnf.env.BJAM_TOOLSET: cnf.env.BJAM_TOOLSET = cnf.options.bjam_toolset @feature('bjam') @after_method('process_rule') def process_bjam(self): if not self.bld.env.BJAM: self.create_task('bjam_creator') self.create_task('bjam_build') self.create_task('bjam_installer') if getattr(self, 'always', False): always_run(bjam_creator) always_run(bjam_build) always_run(bjam_installer) class bjam_creator(Task): ext_out = 'bjam_exe' vars=['BJAM_SRC', 'BJAM_UNAME'] def run(self): env = self.env gen = self.generator path = gen.path bld = gen.bld bjam = gen.bld.root.find_dir(env.BJAM_SRC) if not bjam: error('Can not find bjam source') return -1 bjam_exe_relpath = 'bin.' + env.BJAM_UNAME + '/bjam' bjam_exe = bjam.find_resource(bjam_exe_relpath) if bjam_exe: env.BJAM = bjam_exe.srcpath() return 0 bjam_cmd = ['./build.sh'] debug('runner: ' + bjam.srcpath() + '> ' + str(bjam_cmd)) result = self.exec_command(bjam_cmd, cwd=bjam.srcpath()) if not result == 0: error('bjam failed') return -1 bjam_exe = bjam.find_resource(bjam_exe_relpath) if bjam_exe: env.BJAM = bjam_exe.srcpath() return 0 error('bjam failed') return -1 class bjam_build(Task): ext_in = 'bjam_exe' ext_out = 'install' vars = ['BJAM_TOOLSET'] def run(self): env = self.env gen = self.generator path = gen.path bld = gen.bld if hasattr(gen, 'root'): build_root = path.find_node(gen.root) else: build_root = path jam = bld.srcnode.find_resource(env.BJAM_CONFIG) if jam: debug('bjam: Using jam configuration from ' + jam.srcpath()) jam_rel = jam.relpath_gen(build_root) else: warn('No build configuration in build_config/user-config.jam. Using default') jam_rel = None bjam_exe = bld.srcnode.find_node(env.BJAM) if not bjam_exe: error('env.BJAM is not set') return -1 bjam_exe_rel = bjam_exe.relpath_gen(build_root) cmd = ([bjam_exe_rel] + (['--user-config=' + jam_rel] if jam_rel else []) + ['--stagedir=' + path.get_bld().path_from(build_root)] + ['--debug-configuration'] + ['--with-' + lib for lib in self.generator.target] + (['toolset=' + env.BJAM_TOOLSET] if env.BJAM_TOOLSET else []) + ['link=' + 'shared'] + ['variant=' + 'release'] ) debug('runner: ' + build_root.srcpath() + '> ' + str(cmd)) ret = self.exec_command(cmd, cwd=build_root.srcpath()) if ret != 0: return ret self.set_outputs(path.get_bld().ant_glob('lib/*') + path.get_bld().ant_glob('bin/*')) return 0 class bjam_installer(Task): ext_in = 'install' def run(self): gen = self.generator path = gen.path for idir, pat in [('${LIBDIR}', 'lib/*'), ('${BINDIR}', 'bin/*')]: files = [] for n in path.get_bld().ant_glob(pat): try: t = readlink(n.srcpath()) gen.bld.symlink_as(sep.join([idir, n.name]), t, postpone=False) except OSError: files.append(n) gen.bld.install_files(idir, files, postpone=False) return 0 debian/waf-1.6/waflib/extras/freeimage.py0000664000000000000000000000410512145744415015326 0ustar #!/usr/bin/env python # encoding: utf-8 # # written by Sylvain Rouquette, 2011 ''' To add the freeimage tool to the waf file: $ ./waf-light --tools=compat15,freeimage or, if you have waf >= 1.6.2 $ ./waf update --files=freeimage The wscript will look like: def options(opt): opt.load('compiler_cxx freeimage') def configure(conf): conf.load('compiler_cxx freeimage') # you can call check_freeimage with some parameters. # It's optional on Linux, it's 'mandatory' on Windows if # you didn't use --fi-path on the command-line # conf.check_freeimage(path='FreeImage/Dist', fip=True) def build(bld): bld(source='main.cpp', target='app', use='FREEIMAGE') ''' from waflib import Utils from waflib.Configure import conf def options(opt): opt.add_option('--fi-path', type='string', default='', dest='fi_path', help='''path to the FreeImage directory \ where the files are e.g. /FreeImage/Dist''') opt.add_option('--fip', action='store_true', default=False, dest='fip', help='link with FreeImagePlus') opt.add_option('--fi-static', action='store_true', default=False, dest='fi_static', help="link as shared libraries") @conf def check_freeimage(self, path=None, fip=False): self.start_msg('Checking FreeImage') if not self.env['CXX']: self.fatal('you must load compiler_cxx before loading freeimage') prefix = self.options.fi_static and 'ST' or '' platform = Utils.unversioned_sys_platform() if platform == 'win32': if not path: self.fatal('you must specify the path to FreeImage. \ use --fi-path=/FreeImage/Dist') else: self.env['INCLUDES_FREEIMAGE'] = path self.env['%sLIBPATH_FREEIMAGE' % prefix] = path libs = ['FreeImage'] if self.options.fip: libs.append('FreeImagePlus') if platform == 'win32': self.env['%sLIB_FREEIMAGE' % prefix] = libs else: self.env['%sLIB_FREEIMAGE' % prefix] = [i.lower() for i in libs] self.end_msg('ok') def configure(conf): platform = Utils.unversioned_sys_platform() if platform == 'win32' and not conf.options.fi_path: return conf.check_freeimage(conf.options.fi_path, conf.options.fip) debian/waf-1.6/waflib/extras/smart_continue.py0000664000000000000000000000370512145744415016441 0ustar #! /usr/bin/env python # Thomas Nagy, 2011 # Try to cancel the tasks that cannot run with the option -k when an error occurs: # 1 direct file dependencies # 2 tasks listed in the before/after/ext_in/ext_out attributes from waflib import Task, Runner Task.CANCELED = 4 def cancel_next(self, tsk): if not isinstance(tsk, Task.TaskBase): return if tsk.hasrun >= Task.SKIPPED: # normal execution, no need to do anything here return try: canceled_tasks, canceled_nodes = self.canceled_tasks, self.canceled_nodes except AttributeError: canceled_tasks = self.canceled_tasks = set([]) canceled_nodes = self.canceled_nodes = set([]) try: canceled_nodes.update(tsk.outputs) except AttributeError: pass try: canceled_tasks.add(tsk) except AttributeError: pass def get_out(self): tsk = self.out.get() if not self.stop: self.add_more_tasks(tsk) self.count -= 1 self.dirty = True self.cancel_next(tsk) # new code def error_handler(self, tsk): if not self.bld.keep: self.stop = True self.error.append(tsk) self.cancel_next(tsk) # new code Runner.Parallel.cancel_next = cancel_next Runner.Parallel.get_out = get_out Runner.Parallel.error_handler = error_handler def get_next_task(self): tsk = self.get_next_task_smart_continue() if not tsk: return tsk try: canceled_tasks, canceled_nodes = self.canceled_tasks, self.canceled_nodes except AttributeError: pass else: # look in the tasks that this one is waiting on # if one of them was canceled, cancel this one too for x in tsk.run_after: if x in canceled_tasks: tsk.hasrun = Task.CANCELED self.cancel_next(tsk) break else: # so far so good, now consider the nodes for x in getattr(tsk, 'inputs', []) + getattr(tsk, 'deps', []): if x in canceled_nodes: tsk.hasrun = Task.CANCELED self.cancel_next(tsk) break return tsk Runner.Parallel.get_next_task_smart_continue = Runner.Parallel.get_next_task Runner.Parallel.get_next_task = get_next_task debian/waf-1.6/waflib/extras/fc_solstudio.py0000664000000000000000000000315412145744415016102 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc,fc_config,fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_solstudio') @conf def find_solstudio(conf): """Find the Solaris Studio compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['sunf95', 'f95', 'sunf90', 'f90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_solstudio_version(fc) conf.env.FC_NAME = 'SOL' @conf def solstudio_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-Kpic'] v['FCFLAGS_DEBUG'] = ['-w3'] v['LINKFLAGS_fcshlib'] = ['-G'] v['FCSTLIB_MARKER'] = '-Bstatic' v['FCSHLIB_MARKER'] = '-Bdynamic' v['SONAME_ST'] = '-h %s' @conf def solstudio_modifier_platform(conf): dest_os = conf.env['DEST_OS'] or Utils.unversioned_sys_platform() solstudio_modifier_func = getattr(conf, 'solstudio_modifier_' + dest_os, None) if solstudio_modifier_func: solstudio_modifier_func() @conf def get_solstudio_version(conf, fc): """Get the compiler version""" version_re = re.compile(r"Sun Fortran 95 *(?P\d*)\.(?P\d*)", re.I).search cmd = fc + ['-V'] out, err = fc_config.getoutput(conf,cmd,stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not determine the Sun Studio Fortran version.') k = match.groupdict() conf.env['FC_VERSION'] = (k['major'], k['minor']) def configure(conf): conf.find_solstudio() conf.find_ar() conf.fc_flags() conf.solstudio_flags() conf.solstudio_modifier_platform() debian/waf-1.6/waflib/extras/fc_bgxlf.py0000664000000000000000000000134612145744415015160 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].insert(0, 'fc_bgxlf') @conf def find_bgxlf(conf): fc = conf.find_program(['bgxlf2003_r','bgxlf2003'], var='FC') fc = conf.cmd_to_list(fc) conf.get_xlf_version(fc) conf.env.FC_NAME = 'BGXLF' @conf def bg_flags(self): self.env.SONAME_ST = '' self.env.FCSHLIB_MARKER = '' self.env.FCSTLIB_MARKER = '' self.env.FCFLAGS_fcshlib = ['-fPIC'] self.env.LINKFLAGS_fcshlib = ['-G', '-Wl,-bexpfull'] def configure(conf): conf.find_bgxlf() conf.find_ar() conf.fc_flags() conf.xlf_flags() conf.bg_flags() debian/waf-1.6/waflib/extras/qnxnto.py0000664000000000000000000000364412145744415014740 0ustar #!/usr/bin/env python # encoding: utf-8 # Jérôme Carretero 2011 (zougloub) # QNX neutrino compatibility functions import sys, os from waflib import Utils class Popen(object): """ Popen cannot work on QNX from a threaded program: Forking in threads is not implemented in neutrino. Python's os.popen / spawn / fork won't work when running in threads (they will if in the main program thread) In waf, this happens mostly in build. And the use cases can be replaced by os.system() calls. """ __slots__ = ["prog", "kw", "popen", "verbose"] verbose = 0 def __init__(self, prog, **kw): try: self.prog = prog self.kw = kw self.popen = None if Popen.verbose: sys.stdout.write("Popen created: %r, kw=%r..." % (prog, kw)) do_delegate = kw.get('stdout', None) == -1 and kw.get('stderr', None) == -1 if do_delegate: if Popen.verbose: print("Delegating to real Popen") self.popen = self.real_Popen(prog, **kw) else: if Popen.verbose: print("Emulating") except Exception as e: if Popen.verbose: print("Exception: %s" % e) raise def __getattr__(self, name): if Popen.verbose: sys.stdout.write("Getattr: %s..." % name) if name in Popen.__slots__: if Popen.verbose: print("In slots!") return object.__getattr__(self, name) else: if self.popen is not None: if Popen.verbose: print("from Popen") return getattr(self.popen, name) else: if name == "wait": return self.emu_wait else: raise Exception("subprocess emulation: not implemented: %s" % name) def emu_wait(self): if Popen.verbose: print("emulated wait (%r kw=%r)" % (self.prog, self.kw)) if isinstance(self.prog, str): cmd = self.prog else: cmd = " ".join(self.prog) if 'cwd' in self.kw: cmd = 'cd "%s" && %s' % (self.kw['cwd'], cmd) return os.system(cmd) if sys.platform == "qnx6": Popen.real_Popen = Utils.subprocess.Popen Utils.subprocess.Popen = Popen debian/waf-1.6/waflib/extras/fsc.py0000664000000000000000000000372312145744415014162 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Experimental F# stuff FSC="mono /path/to/fsc.exe" waf configure build """ from waflib import Utils, Task, Options, Logs, Errors from waflib.TaskGen import before_method, after_method, feature from waflib.Tools import ccroot, cs from waflib.Configure import conf ccroot.USELIB_VARS['fsc'] = set(['CSFLAGS', 'ASSEMBLIES', 'RESOURCES']) @feature('fs') @before_method('process_source') def apply_fsc(self): cs_nodes = [] no_nodes = [] for x in self.to_nodes(self.source): if x.name.endswith('.fs'): cs_nodes.append(x) else: no_nodes.append(x) self.source = no_nodes bintype = getattr(self, 'type', self.gen.endswith('.dll') and 'library' or 'exe') self.cs_task = tsk = self.create_task('fsc', cs_nodes, self.path.find_or_declare(self.gen)) tsk.env.CSTYPE = '/target:%s' % bintype tsk.env.OUT = '/out:%s' % tsk.outputs[0].abspath() inst_to = getattr(self, 'install_path', bintype=='exe' and '${BINDIR}' or '${LIBDIR}') if inst_to: # note: we are making a copy, so the files added to cs_task.outputs won't be installed automatically mod = getattr(self, 'chmod', bintype=='exe' and Utils.O755 or Utils.O644) self.install_task = self.bld.install_files(inst_to, self.cs_task.outputs[:], env=self.env, chmod=mod) feature('fs')(cs.use_cs) after_method('apply_fsc')(cs.use_cs) feature('fs')(cs.debug_cs) after_method('apply_fsc', 'use_cs')(cs.debug_cs) class fsc(Task.Task): """ Compile F# files """ color = 'YELLOW' run_str = '${FSC} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' def configure(conf): """ Find a F# compiler, set the variable FSC for the compiler and FS_NAME (mono or fsc) """ conf.find_program(['fsc.exe', 'fsharpc'], var='FSC') conf.env.FSC = conf.cmd_to_list(conf.env.FSC) conf.env.ASS_ST = '/r:%s' conf.env.RES_ST = '/resource:%s' conf.env.CS_NAME = 'fsc' if str(conf.env.FSC).lower().find('fsharpc') > -1: conf.env.CS_NAME = 'mono' debian/waf-1.6/waflib/extras/netcache_client.py0000664000000000000000000001702712145744415016521 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ A client for the network cache (playground/netcache/). Launch the server with: ./netcache_server, then use it for the builds by adding the following: def options(opt): opt.load('netcache_client') The parameters should be present in the environment in the form: NETCACHE=host:port@mode waf configure build where: mode: PUSH, PULL, PUSH_PULL host: host where the server resides, for example 127.0.0.1 port: by default the server runs on port 51200 The cache can be enabled for the build only: def options(opt): opt.load('netcache_client', funs=[]) def build(bld): bld.setup_netcache('localhost', 51200, 'PUSH_PULL') """ import os, socket, time, atexit from waflib import Task, Logs, Utils, Build, Options, Runner from waflib.Configure import conf BUF = 8192 * 16 HEADER_SIZE = 128 MODES = ['PUSH', 'PULL', 'PUSH_PULL'] STALE_TIME = 30 # seconds GET = 'GET' PUT = 'PUT' LST = 'LST' BYE = 'BYE' all_sigs_in_cache = (0.0, []) active_connections = Runner.Queue(0) def get_connection(): # return a new connection... do not forget to release it! try: ret = active_connections.get(block=False) except Exception: ret = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ret.connect(Task.net_cache[:2]) return ret def release_connection(conn, msg=''): if conn: active_connections.put(conn) def close_connection(conn, msg=''): if conn: data = '%s,%s' % (BYE, msg) try: conn.send(data.ljust(HEADER_SIZE)) except: pass try: conn.close() except: pass def close_all(): while active_connections.qsize(): conn = active_connections.get() try: close_connection(conn) except: pass atexit.register(close_all) def read_header(conn): cnt = 0 buf = [] while cnt < HEADER_SIZE: data = conn.recv(HEADER_SIZE - cnt) if not data: #import traceback #traceback.print_stack() raise ValueError('connection ended when reading a header %r' % buf) buf.append(data) cnt += len(data) return ''.join(buf) def check_cache(conn, ssig): """ List the files on the server, this is an optimization because it assumes that concurrent builds are rare """ global all_sigs_in_cache if not STALE_TIME: return if time.time() - all_sigs_in_cache[0] > STALE_TIME: params = (LST,'') conn.send(','.join(params).ljust(HEADER_SIZE)) # read what is coming back ret = read_header(conn) size = int(ret.split(',')[0]) buf = [] cnt = 0 while cnt < size: data = conn.recv(min(BUF, size-cnt)) if not data: raise ValueError('connection ended %r %r' % (cnt, size)) buf.append(data) cnt += len(data) all_sigs_in_cache = (time.time(), ''.join(buf).split('\n')) Logs.debug('netcache: server cache has %r entries' % len(all_sigs_in_cache[1])) if not ssig in all_sigs_in_cache[1]: raise ValueError('no file %s in cache' % ssig) class MissingFile(Exception): pass def recv_file(conn, ssig, count, p): check_cache(conn, ssig) params = (GET, ssig, str(count)) conn.send(','.join(params).ljust(HEADER_SIZE)) data = read_header(conn) size = int(data.split(',')[0]) if size == -1: raise MissingFile('no file %s - %s in cache' % (ssig, count)) # get the file, writing immediately # TODO a tmp file would be better f = open(p, 'wb') cnt = 0 while cnt < size: data = conn.recv(min(BUF, size-cnt)) if not data: raise ValueError('connection ended %r %r' % (cnt, size)) f.write(data) cnt += len(data) f.close() def put_data(conn, ssig, cnt, p): #print "pushing %r %r %r" % (ssig, cnt, p) size = os.stat(p).st_size params = (PUT, ssig, str(cnt), str(size)) conn.send(','.join(params).ljust(HEADER_SIZE)) f = open(p, 'rb') cnt = 0 while cnt < size: r = f.read(min(BUF, size-cnt)) while r: k = conn.send(r) if not k: raise ValueError('connection ended') cnt += k r = r[k:] #def put_data(conn, ssig, cnt, p): # size = os.stat(p).st_size # params = (PUT, ssig, str(cnt), str(size)) # conn.send(','.join(params).ljust(HEADER_SIZE)) # conn.send(','*size) # params = (BYE, 'he') # conn.send(','.join(params).ljust(HEADER_SIZE)) def can_retrieve_cache(self): if not Task.net_cache: return False if not self.outputs: return False if Task.net_cache[-1] == 'PUSH': return self.cached = False cnt = 0 sig = self.signature() ssig = self.uid().encode('hex') + sig.encode('hex') conn = None err = False try: try: conn = get_connection() for node in self.outputs: p = node.abspath() recv_file(conn, ssig, cnt, p) cnt += 1 except MissingFile as e: Logs.debug('netcache: file is not in the cache %r' % e) err = True except Exception as e: Logs.debug('netcache: could not get the files %r' % e) err = True # broken connection? remove this one close_connection(conn) conn = None finally: release_connection(conn) if err: return False for node in self.outputs: node.sig = sig #if self.generator.bld.progress_bar < 1: # self.generator.bld.to_log('restoring from cache %r\n' % node.abspath()) self.cached = True return True @Utils.run_once def put_files_cache(self): if not Task.net_cache: return if not self.outputs: return if Task.net_cache[-1] == 'PULL': return if getattr(self, 'cached', None): return #print "called put_files_cache", id(self) bld = self.generator.bld sig = self.signature() ssig = self.uid().encode('hex') + sig.encode('hex') conn = None cnt = 0 try: for node in self.outputs: # We could re-create the signature of the task with the signature of the outputs # in practice, this means hashing the output files # this is unnecessary try: if not conn: conn = get_connection() put_data(conn, ssig, cnt, node.abspath()) except Exception as e: Logs.debug("netcache: could not push the files %r" % e) # broken connection? remove this one close_connection(conn) conn = None cnt += 1 finally: release_connection(conn) bld.task_sigs[self.uid()] = self.cache_sig def hash_env_vars(self, env, vars_lst): if not env.table: env = env.parent if not env: return Utils.SIG_NIL idx = str(id(env)) + str(vars_lst) try: cache = self.cache_env except AttributeError: cache = self.cache_env = {} else: try: return self.cache_env[idx] except KeyError: pass v = str([env[a] for a in vars_lst]) v = v.replace(self.srcnode.abspath(), '') # here m = Utils.md5() m.update(v.encode()) ret = m.digest() Logs.debug('envhash: %r %r', ret, v) cache[idx] = ret return ret def uid(self): try: return self.uid_ except AttributeError: m = Utils.md5() src = self.generator.bld.srcnode up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.path_from(src).encode()) self.uid_ = m.digest() return self.uid_ @conf def setup_netcache(ctx, host, port, mode): Logs.warn('Using the network cache %s, %s, %s' % (host, port, mode)) Task.net_cache = (host, port, mode) Task.Task.can_retrieve_cache = can_retrieve_cache Task.Task.put_files_cache = put_files_cache Task.Task.uid = uid Build.BuildContext.hash_env_vars = hash_env_vars ctx.cache_global = Options.cache_global = True def options(opt): if not 'NETCACHE' in os.environ: Logs.warn('the network cache is disabled, set NETCACHE=host:port@mode to enable') else: v = os.environ['NETCACHE'] if v in MODES: host = socket.gethostname() port = 51200 mode = v else: mode = 'PUSH_PULL' host, port = v.split(':') if port.find('@'): port, mode = port.split('@') port = int(port) if not mode in MODES: opt.fatal('Invalid mode %s not in %r' % (mode, MODES)) setup_netcache(opt, host, port, mode) debian/waf-1.6/waflib/extras/fluid.py0000664000000000000000000000152512145744415014510 0ustar #!/usr/bin/python # encoding: utf-8 # Grygoriy Fuchedzhy 2009 """ Compile fluid files (fltk graphic library). Use the 'fluid' feature in conjuction with the 'cxx' feature. """ from waflib import Task from waflib.TaskGen import extension class fluid(Task.Task): color = 'BLUE' ext_out = ['.h'] run_str = '${FLUID} -c -o ${TGT[0].abspath()} -h ${TGT[1].abspath()} ${SRC}' @extension('.fl') def fluid(self, node): """add the .fl to the source list; the cxx file generated will be compiled when possible""" cpp = node.change_ext('.cpp') hpp = node.change_ext('.hpp') self.create_task('fluid', node, [cpp, hpp]) if 'cxx' in self.features: self.source.append(cpp) def configure(conf): conf.find_program('fluid', var='FLUID') conf.check_cfg(path='fltk-config', package='', args='--cxxflags --ldflags', uselib_store='FLTK', mandatory=True) debian/waf-1.6/waflib/extras/fsb.py0000664000000000000000000000107412145744415014156 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Fully sequential builds The previous tasks from task generators are re-processed, and this may lead to speed issues Yet, if you are using this, speed is probably a minor concern """ from waflib import Build def options(opt): pass def configure(conf): pass class FSBContext(Build.BuildContext): def __call__(self, *k, **kw): ret = Build.BuildContext.__call__(self, *k, **kw) # evaluate the results immediately Build.BuildContext.compile(self) return ret def compile(self): pass debian/waf-1.6/waflib/extras/fc_pgfortran.py0000664000000000000000000000340012145744415016051 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import re from waflib import Utils from waflib.Tools import fc, fc_config, fc_scan from waflib.Configure import conf from waflib.Tools.compiler_fc import fc_compiler fc_compiler['linux'].append('fc_pgfortran') @conf def find_pgfortran(conf): """Find the PGI fortran compiler (will look in the environment variable 'FC')""" fc = conf.find_program(['pgfortran', 'pgf95', 'pgf90'], var='FC') fc = conf.cmd_to_list(fc) conf.get_pgfortran_version(fc) conf.env.FC_NAME = 'PGFC' @conf def pgfortran_flags(conf): v = conf.env v['FCFLAGS_fcshlib'] = ['-shared'] v['FCFLAGS_DEBUG'] = ['-Minform=inform', '-Mstandard'] # why not v['FCSTLIB_MARKER'] = '-Bstatic' v['FCSHLIB_MARKER'] = '-Bdynamic' v['SONAME_ST'] = '-soname %s' @conf def get_pgfortran_version(conf,fc): version_re = re.compile(r"The Portland Group", re.I).search cmd = fc + ['-V'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not verify PGI signature') cmd = fc + ['-help=variable'] out,err = fc_config.getoutput(conf, cmd, stdin=False) if out.find('COMPVER')<0: conf.fatal('Could not determine the compiler type') k = {} prevk = '' out = out.split('\n') for line in out: lst = line.partition('=') if lst[1] == '=': key = lst[0].rstrip() if key == '': key = prevk val = lst[2].rstrip() k[key] = val else: prevk = line.partition(' ')[0] def isD(var): return var in k def isT(var): return var in k and k[var]!='0' conf.env['FC_VERSION'] = (k['COMPVER'].split('.')) def configure(conf): conf.find_pgfortran() conf.find_ar() conf.fc_flags() conf.pgfortran_flags() debian/waf-1.6/waflib/extras/swig.py0000664000000000000000000001050612145744415014355 0ustar #! /usr/bin/env python # encoding: UTF-8 # Petar Forai # Thomas Nagy 2008-2010 (ita) import re from waflib import Task, Utils, Logs from waflib.TaskGen import extension, feature, after_method from waflib.Configure import conf from waflib.Tools import c_preproc """ tasks have to be added dynamically: - swig interface files may be created at runtime - the module name may be unknown in advance """ SWIG_EXTS = ['.swig', '.i'] re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) re_2 = re.compile('%include "(.*)"', re.M) re_3 = re.compile('#include "(.*)"', re.M) class swig(Task.Task): color = 'BLUE' run_str = '${SWIG} ${SWIGFLAGS} ${SWIGPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${SRC}' ext_out = ['.h'] # might produce .h files although it is not mandatory def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not getattr(self, 'init_outputs', None): self.init_outputs = True if not getattr(self, 'module', None): # search the module name txt = self.inputs[0].read() m = re_module.search(txt) if not m: raise ValueError("could not find the swig module name") self.module = m.group(1) swig_c(self) # add the language-specific output files as nodes # call funs in the dict swig_langs for x in self.env['SWIGFLAGS']: # obtain the language x = x[1:] try: fun = swig_langs[x] except KeyError: pass else: fun(self) return super(swig, self).runnable_status() def scan(self): "scan for swig dependencies, climb the .i files" env = self.env lst_src = [] seen = [] to_see = [self.inputs[0]] while to_see: node = to_see.pop(0) if node in seen: continue seen.append(node) lst_src.append(node) # read the file code = node.read() code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) # find .i files and project headers names = re_2.findall(code) + re_3.findall(code) for n in names: for d in self.generator.includes_nodes + [node.parent]: u = d.find_resource(n) if u: to_see.append(u) break else: Logs.warn('could not find %r' % n) return (lst_src, []) # provide additional language processing swig_langs = {} def swigf(fun): swig_langs[fun.__name__.replace('swig_', '')] = fun swig.swigf = swigf def swig_c(self): ext = '.swigwrap_%d.c' % self.generator.idx flags = self.env['SWIGFLAGS'] if '-c++' in flags: ext += 'xx' out_node = self.inputs[0].parent.find_or_declare(self.module + ext) if '-c++' in flags: c_tsk = self.generator.cxx_hook(out_node) else: c_tsk = self.generator.c_hook(out_node) c_tsk.set_run_after(self) ge = self.generator.bld.producer ge.outstanding.insert(0, c_tsk) ge.total += 1 try: ltask = self.generator.link_task except AttributeError: pass else: ltask.set_run_after(c_tsk) ltask.inputs.append(c_tsk.outputs[0]) self.outputs.append(out_node) if not '-o' in self.env['SWIGFLAGS']: self.env.append_value('SWIGFLAGS', ['-o', self.outputs[0].abspath()]) @swigf def swig_python(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.py')) @swigf def swig_ocaml(tsk): tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.ml')) tsk.set_outputs(tsk.inputs[0].parent.find_or_declare(tsk.module + '.mli')) @extension(*SWIG_EXTS) def i_file(self, node): # the task instance tsk = self.create_task('swig') tsk.set_inputs(node) tsk.module = getattr(self, 'swig_module', None) flags = self.to_list(getattr(self, 'swig_flags', [])) tsk.env.append_value('SWIGFLAGS', flags) # looks like this is causing problems #if not '-outdir' in flags: # tsk.env.append_value('SWIGFLAGS', ['-outdir', node.parent.abspath()]) @conf def check_swig_version(self): """Check for a minimum swig version like conf.check_swig_version('1.3.28') or conf.check_swig_version((1,3,28)) """ reg_swig = re.compile(r'SWIG Version\s(.*)', re.M) swig_out = self.cmd_and_log('%s -version' % self.env['SWIG']) swigver = tuple([int(s) for s in reg_swig.findall(swig_out)[0].split('.')]) self.env['SWIG_VERSION'] = swigver msg = 'Checking for swig version' self.msg(msg, '.'.join(map(str, swigver))) return swigver def configure(conf): swig = conf.find_program('swig', var='SWIG') conf.env.SWIGPATH_ST = '-I%s' debian/waf-1.6/waflib/extras/relocation.py0000664000000000000000000000435212145744415015545 0ustar #! /usr/bin/env python # encoding: utf-8 """ Waf 1.6 Try to detect if the project directory was relocated, and if it was, change the node representing the project directory. Just call: waf configure build Note that if the project directory name changes, the signatures for the tasks using files in that directory will change, causing a partial build. """ import os from waflib import Build, ConfigSet, Task, Utils, Errors from waflib.TaskGen import feature, before_method, after_method EXTRA_LOCK = '.old_srcdir' old1 = Build.BuildContext.store def store(self): old1(self) db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() env.SRCDIR = self.srcnode.abspath() env.store(db) Build.BuildContext.store = store old2 = Build.BuildContext.init_dirs def init_dirs(self): if not (os.path.isabs(self.top_dir) and os.path.isabs(self.out_dir)): raise Errors.WafError('The project was not configured: run "waf configure" first!') srcdir = None db = os.path.join(self.variant_dir, EXTRA_LOCK) env = ConfigSet.ConfigSet() try: env.load(db) srcdir = env.SRCDIR except: pass if srcdir: d = self.root.find_node(srcdir) if d and srcdir != self.top_dir and getattr(d, 'children', ''): srcnode = self.root.make_node(self.top_dir) print("relocating the source directory %r -> %r" % (srcdir, self.top_dir)) srcnode.children = {} for (k, v) in d.children.items(): srcnode.children[k] = v v.parent = srcnode d.children = {} old2(self) Build.BuildContext.init_dirs = init_dirs def uid(self): try: return self.uid_ except AttributeError: # this is not a real hot zone, but we want to avoid surprizes here m = Utils.md5() up = m.update up(self.__class__.__name__.encode()) for x in self.inputs + self.outputs: up(x.path_from(x.ctx.srcnode).encode()) self.uid_ = m.digest() return self.uid_ Task.Task.uid = uid @feature('c', 'cxx', 'd', 'go', 'asm', 'fc', 'includes') @after_method('propagate_uselib_vars', 'process_source') def apply_incpaths(self): lst = self.to_incnodes(self.to_list(getattr(self, 'includes', [])) + self.env['INCLUDES']) self.includes_nodes = lst bld = self.bld self.env['INCPATHS'] = [x.is_child_of(bld.srcnode) and x.path_from(bld.bldnode) or x.abspath() for x in lst] debian/waf-1.6/waflib/extras/subprocess.py0000664000000000000000000005103712145744415015600 0ustar # borrowed from python 2.5.2c1 # Copyright (c) 2003-2005 by Peter Astrand # Licensed to PSF under a Contributor Agreement. import sys mswindows = (sys.platform == "win32") import os import types import traceback import gc class CalledProcessError(Exception): def __init__(self, returncode, cmd): self.returncode = returncode self.cmd = cmd def __str__(self): return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) if mswindows: import threading import msvcrt if 0: import pywintypes from win32api import GetStdHandle, STD_INPUT_HANDLE, \ STD_OUTPUT_HANDLE, STD_ERROR_HANDLE from win32api import GetCurrentProcess, DuplicateHandle, \ GetModuleFileName, GetVersion from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE from win32pipe import CreatePipe from win32process import CreateProcess, STARTUPINFO, \ GetExitCodeProcess, STARTF_USESTDHANDLES, \ STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0 else: from _subprocess import * class STARTUPINFO: dwFlags = 0 hStdInput = None hStdOutput = None hStdError = None wShowWindow = 0 class pywintypes: error = IOError else: import select import errno import fcntl import pickle __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"] try: MAXFD = os.sysconf("SC_OPEN_MAX") except: MAXFD = 256 try: False except NameError: False = 0 True = 1 _active = [] def _cleanup(): for inst in _active[:]: if inst.poll(_deadstate=sys.maxint) >= 0: try: _active.remove(inst) except ValueError: pass PIPE = -1 STDOUT = -2 def call(*popenargs, **kwargs): return Popen(*popenargs, **kwargs).wait() def check_call(*popenargs, **kwargs): retcode = call(*popenargs, **kwargs) cmd = kwargs.get("args") if cmd is None: cmd = popenargs[0] if retcode: raise CalledProcessError(retcode, cmd) return retcode def list2cmdline(seq): result = [] needquote = False for arg in seq: bs_buf = [] if result: result.append(' ') needquote = (" " in arg) or ("\t" in arg) or arg == "" if needquote: result.append('"') for c in arg: if c == '\\': bs_buf.append(c) elif c == '"': result.append('\\' * len(bs_buf)*2) bs_buf = [] result.append('\\"') else: if bs_buf: result.extend(bs_buf) bs_buf = [] result.append(c) if bs_buf: result.extend(bs_buf) if needquote: result.extend(bs_buf) result.append('"') return ''.join(result) class Popen(object): def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0): _cleanup() self._child_created = False if not isinstance(bufsize, (int, long)): raise TypeError("bufsize must be an integer") if mswindows: if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows platforms") if close_fds: raise ValueError("close_fds is not supported on Windows platforms") else: if startupinfo is not None: raise ValueError("startupinfo is only supported on Windows platforms") if creationflags != 0: raise ValueError("creationflags is only supported on Windows platforms") self.stdin = None self.stdout = None self.stderr = None self.pid = None self.returncode = None self.universal_newlines = universal_newlines (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) = self._get_handles(stdin, stdout, stderr) self._execute_child(args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) if mswindows: if stdin is None and p2cwrite is not None: os.close(p2cwrite) p2cwrite = None if stdout is None and c2pread is not None: os.close(c2pread) c2pread = None if stderr is None and errread is not None: os.close(errread) errread = None if p2cwrite: self.stdin = os.fdopen(p2cwrite, 'wb', bufsize) if c2pread: if universal_newlines: self.stdout = os.fdopen(c2pread, 'rU', bufsize) else: self.stdout = os.fdopen(c2pread, 'rb', bufsize) if errread: if universal_newlines: self.stderr = os.fdopen(errread, 'rU', bufsize) else: self.stderr = os.fdopen(errread, 'rb', bufsize) def _translate_newlines(self, data): data = data.replace("\r\n", "\n") data = data.replace("\r", "\n") return data def __del__(self, sys=sys): if not self._child_created: return self.poll(_deadstate=sys.maxint) if self.returncode is None and _active is not None: _active.append(self) def communicate(self, input=None): if [self.stdin, self.stdout, self.stderr].count(None) >= 2: stdout = None stderr = None if self.stdin: if input: self.stdin.write(input) self.stdin.close() elif self.stdout: stdout = self.stdout.read() elif self.stderr: stderr = self.stderr.read() self.wait() return (stdout, stderr) return self._communicate(input) if mswindows: def _get_handles(self, stdin, stdout, stderr): if stdin is None and stdout is None and stderr is None: return (None, None, None, None, None, None) p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin is None: p2cread = GetStdHandle(STD_INPUT_HANDLE) if p2cread is not None: pass elif stdin is None or stdin == PIPE: p2cread, p2cwrite = CreatePipe(None, 0) p2cwrite = p2cwrite.Detach() p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0) elif isinstance(stdin, int): p2cread = msvcrt.get_osfhandle(stdin) else: p2cread = msvcrt.get_osfhandle(stdin.fileno()) p2cread = self._make_inheritable(p2cread) if stdout is None: c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE) if c2pwrite is not None: pass elif stdout is None or stdout == PIPE: c2pread, c2pwrite = CreatePipe(None, 0) c2pread = c2pread.Detach() c2pread = msvcrt.open_osfhandle(c2pread, 0) elif isinstance(stdout, int): c2pwrite = msvcrt.get_osfhandle(stdout) else: c2pwrite = msvcrt.get_osfhandle(stdout.fileno()) c2pwrite = self._make_inheritable(c2pwrite) if stderr is None: errwrite = GetStdHandle(STD_ERROR_HANDLE) if errwrite is not None: pass elif stderr is None or stderr == PIPE: errread, errwrite = CreatePipe(None, 0) errread = errread.Detach() errread = msvcrt.open_osfhandle(errread, 0) elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): errwrite = msvcrt.get_osfhandle(stderr) else: errwrite = msvcrt.get_osfhandle(stderr.fileno()) errwrite = self._make_inheritable(errwrite) return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _make_inheritable(self, handle): return DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 0, 1, DUPLICATE_SAME_ACCESS) def _find_w9xpopen(self): w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)), "w9xpopen.exe") if not os.path.exists(w9xpopen): w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix), "w9xpopen.exe") if not os.path.exists(w9xpopen): raise RuntimeError("Cannot locate w9xpopen.exe, which is needed for Popen to work with your shell or platform.") return w9xpopen def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): if not isinstance(args, types.StringTypes): args = list2cmdline(args) if startupinfo is None: startupinfo = STARTUPINFO() if None not in (p2cread, c2pwrite, errwrite): startupinfo.dwFlags |= STARTF_USESTDHANDLES startupinfo.hStdInput = p2cread startupinfo.hStdOutput = c2pwrite startupinfo.hStdError = errwrite if shell: startupinfo.dwFlags |= STARTF_USESHOWWINDOW startupinfo.wShowWindow = SW_HIDE comspec = os.environ.get("COMSPEC", "cmd.exe") args = comspec + " /c " + args if (GetVersion() >= 0x80000000L or os.path.basename(comspec).lower() == "command.com"): w9xpopen = self._find_w9xpopen() args = '"%s" %s' % (w9xpopen, args) creationflags |= CREATE_NEW_CONSOLE try: hp, ht, pid, tid = CreateProcess(executable, args, None, None, 1, creationflags, env, cwd, startupinfo) except pywintypes.error, e: raise WindowsError(*e.args) self._child_created = True self._handle = hp self.pid = pid ht.Close() if p2cread is not None: p2cread.Close() if c2pwrite is not None: c2pwrite.Close() if errwrite is not None: errwrite.Close() def poll(self, _deadstate=None): if self.returncode is None: if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0: self.returncode = GetExitCodeProcess(self._handle) return self.returncode def wait(self): if self.returncode is None: obj = WaitForSingleObject(self._handle, INFINITE) self.returncode = GetExitCodeProcess(self._handle) return self.returncode def _readerthread(self, fh, buffer): buffer.append(fh.read()) def _communicate(self, input): stdout = None stderr = None if self.stdout: stdout = [] stdout_thread = threading.Thread(target=self._readerthread, args=(self.stdout, stdout)) stdout_thread.setDaemon(True) stdout_thread.start() if self.stderr: stderr = [] stderr_thread = threading.Thread(target=self._readerthread, args=(self.stderr, stderr)) stderr_thread.setDaemon(True) stderr_thread.start() if self.stdin: if input is not None: self.stdin.write(input) self.stdin.close() if self.stdout: stdout_thread.join() if self.stderr: stderr_thread.join() if stdout is not None: stdout = stdout[0] if stderr is not None: stderr = stderr[0] if self.universal_newlines and hasattr(file, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) else: def _get_handles(self, stdin, stdout, stderr): p2cread, p2cwrite = None, None c2pread, c2pwrite = None, None errread, errwrite = None, None if stdin is None: pass elif stdin == PIPE: p2cread, p2cwrite = os.pipe() elif isinstance(stdin, int): p2cread = stdin else: p2cread = stdin.fileno() if stdout is None: pass elif stdout == PIPE: c2pread, c2pwrite = os.pipe() elif isinstance(stdout, int): c2pwrite = stdout else: c2pwrite = stdout.fileno() if stderr is None: pass elif stderr == PIPE: errread, errwrite = os.pipe() elif stderr == STDOUT: errwrite = c2pwrite elif isinstance(stderr, int): errwrite = stderr else: errwrite = stderr.fileno() return (p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) def _set_cloexec_flag(self, fd): try: cloexec_flag = fcntl.FD_CLOEXEC except AttributeError: cloexec_flag = 1 old = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) def _close_fds(self, but): for i in xrange(3, MAXFD): if i == but: continue try: os.close(i) except: pass def _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): if isinstance(args, types.StringTypes): args = [args] else: args = list(args) if shell: args = ["/bin/sh", "-c"] + args if executable is None: executable = args[0] errpipe_read, errpipe_write = os.pipe() self._set_cloexec_flag(errpipe_write) gc_was_enabled = gc.isenabled() gc.disable() try: self.pid = os.fork() except: if gc_was_enabled: gc.enable() raise self._child_created = True if self.pid == 0: try: if p2cwrite: os.close(p2cwrite) if c2pread: os.close(c2pread) if errread: os.close(errread) os.close(errpipe_read) if p2cread: os.dup2(p2cread, 0) if c2pwrite: os.dup2(c2pwrite, 1) if errwrite: os.dup2(errwrite, 2) if p2cread and p2cread not in (0,): os.close(p2cread) if c2pwrite and c2pwrite not in (p2cread, 1): os.close(c2pwrite) if errwrite and errwrite not in (p2cread, c2pwrite, 2): os.close(errwrite) if close_fds: self._close_fds(but=errpipe_write) if cwd is not None: os.chdir(cwd) if preexec_fn: apply(preexec_fn) if env is None: os.execvp(executable, args) else: os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) os._exit(255) if gc_was_enabled: gc.enable() os.close(errpipe_write) if p2cread and p2cwrite: os.close(p2cread) if c2pwrite and c2pread: os.close(c2pwrite) if errwrite and errread: os.close(errwrite) data = os.read(errpipe_read, 1048576) os.close(errpipe_read) if data != "": os.waitpid(self.pid, 0) child_exception = pickle.loads(data) raise child_exception def _handle_exitstatus(self, sts): if os.WIFSIGNALED(sts): self.returncode = -os.WTERMSIG(sts) elif os.WIFEXITED(sts): self.returncode = os.WEXITSTATUS(sts) else: raise RuntimeError("Unknown child exit status!") def poll(self, _deadstate=None): if self.returncode is None: try: pid, sts = os.waitpid(self.pid, os.WNOHANG) if pid == self.pid: self._handle_exitstatus(sts) except os.error: if _deadstate is not None: self.returncode = _deadstate return self.returncode def wait(self): if self.returncode is None: pid, sts = os.waitpid(self.pid, 0) self._handle_exitstatus(sts) return self.returncode def _communicate(self, input): read_set = [] write_set = [] stdout = None stderr = None if self.stdin: self.stdin.flush() if input: write_set.append(self.stdin) else: self.stdin.close() if self.stdout: read_set.append(self.stdout) stdout = [] if self.stderr: read_set.append(self.stderr) stderr = [] input_offset = 0 while read_set or write_set: rlist, wlist, xlist = select.select(read_set, write_set, []) if self.stdin in wlist: bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512)) input_offset += bytes_written if input_offset >= len(input): self.stdin.close() write_set.remove(self.stdin) if self.stdout in rlist: data = os.read(self.stdout.fileno(), 1024) if data == "": self.stdout.close() read_set.remove(self.stdout) stdout.append(data) if self.stderr in rlist: data = os.read(self.stderr.fileno(), 1024) if data == "": self.stderr.close() read_set.remove(self.stderr) stderr.append(data) if stdout is not None: stdout = ''.join(stdout) if stderr is not None: stderr = ''.join(stderr) if self.universal_newlines and hasattr(file, 'newlines'): if stdout: stdout = self._translate_newlines(stdout) if stderr: stderr = self._translate_newlines(stderr) self.wait() return (stdout, stderr) debian/waf-1.6/waflib/extras/compat15.py0000664000000000000000000002204012145744415015031 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ This file is provided to enable compatibility with waf 1.5, it will be removed in waf 1.7 """ import sys from waflib import ConfigSet, Logs, Options, Scripting, Task, Build, Configure, Node, Runner, TaskGen, Utils, Errors, Context # the following is to bring some compatibility with waf 1.5 "import waflib.Configure → import Configure" sys.modules['Environment'] = ConfigSet ConfigSet.Environment = ConfigSet.ConfigSet sys.modules['Logs'] = Logs sys.modules['Options'] = Options sys.modules['Scripting'] = Scripting sys.modules['Task'] = Task sys.modules['Build'] = Build sys.modules['Configure'] = Configure sys.modules['Node'] = Node sys.modules['Runner'] = Runner sys.modules['TaskGen'] = TaskGen sys.modules['Utils'] = Utils from waflib.Tools import c_preproc sys.modules['preproc'] = c_preproc from waflib.Tools import c_config sys.modules['config_c'] = c_config ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive ConfigSet.ConfigSet.set_variant = Utils.nada Build.BuildContext.add_subdirs = Build.BuildContext.recurse Build.BuildContext.new_task_gen = Build.BuildContext.__call__ Build.BuildContext.is_install = 0 Node.Node.relpath_gen = Node.Node.path_from def name_to_obj(self, s, env=None): Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') return self.get_tgen_by_name(s) Build.BuildContext.name_to_obj = name_to_obj def env_of_name(self, name): try: return self.all_envs[name] except KeyError: Logs.error('no such environment: '+name) return None Build.BuildContext.env_of_name = env_of_name def set_env_name(self, name, env): self.all_envs[name] = env return env Configure.ConfigurationContext.set_env_name = set_env_name def retrieve(self, name, fromenv=None): try: env = self.all_envs[name] except KeyError: env = ConfigSet.ConfigSet() self.prepare_env(env) self.all_envs[name] = env else: if fromenv: Logs.warn("The environment %s may have been configured already" % name) return env Configure.ConfigurationContext.retrieve = retrieve Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load Configure.conftest = Configure.conf Configure.ConfigurationError = Errors.ConfigurationError Options.OptionsContext.sub_options = Options.OptionsContext.recurse Options.OptionsContext.tool_options = Context.Context.load Options.Handler = Options.OptionsContext Task.simple_task_type = Task.task_type_from_func = Task.task_factory Task.TaskBase.classes = Task.classes def setitem(self, key, value): if key.startswith('CCFLAGS'): key = key[1:] self.table[key] = value ConfigSet.ConfigSet.__setitem__ = setitem @TaskGen.feature('d') @TaskGen.before('apply_incpaths') def old_importpaths(self): if getattr(self, 'importpaths', []): self.includes = self.importpaths from waflib import Context eld = Context.load_tool def load_tool(*k, **kw): ret = eld(*k, **kw) if 'set_options' in ret.__dict__: Logs.warn('compat: rename "set_options" to options') ret.options = ret.set_options if 'detect' in ret.__dict__: Logs.warn('compat: rename "detect" to "configure"') ret.configure = ret.detect return ret Context.load_tool = load_tool rev = Context.load_module def load_module(path): ret = rev(path) if 'set_options' in ret.__dict__: Logs.warn('compat: rename "set_options" to "options" (%r)' % path) ret.options = ret.set_options if 'srcdir' in ret.__dict__: Logs.warn('compat: rename "srcdir" to "top" (%r)' % path) ret.top = ret.srcdir if 'blddir' in ret.__dict__: Logs.warn('compat: rename "blddir" to "out" (%r)' % path) ret.out = ret.blddir return ret Context.load_module = load_module old_post = TaskGen.task_gen.post def post(self): self.features = self.to_list(self.features) if 'cc' in self.features: Logs.warn('compat: the feature cc does not exist anymore (use "c")') self.features.remove('cc') self.features.append('c') if 'cstaticlib' in self.features: Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') self.features.remove('cstaticlib') self.features.append(('cxx' in self.features) and 'cxxstlib' or 'cstlib') if getattr(self, 'ccflags', None): Logs.warn('compat: "ccflags" was renamed to "cflags"') self.cflags = self.ccflags return old_post(self) TaskGen.task_gen.post = post def waf_version(*k, **kw): Logs.warn('wrong version (waf_version was removed in waf 1.6)') Utils.waf_version = waf_version import os @TaskGen.feature('c', 'cxx', 'd') @TaskGen.before('apply_incpaths', 'propagate_uselib_vars') @TaskGen.after('apply_link', 'process_source') def apply_uselib_local(self): """ process the uselib_local attribute execute after apply_link because of the execution order set on 'link_task' """ env = self.env from waflib.Tools.ccroot import stlink_task # 1. the case of the libs defined in the project (visit ancestors first) # the ancestors external libraries (uselib) will be prepended self.uselib = self.to_list(getattr(self, 'uselib', [])) self.includes = self.to_list(getattr(self, 'includes', [])) names = self.to_list(getattr(self, 'uselib_local', [])) get = self.bld.get_tgen_by_name seen = set([]) tmp = Utils.deque(names) # consume a copy of the list of names if tmp: Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') while tmp: lib_name = tmp.popleft() # visit dependencies only once if lib_name in seen: continue y = get(lib_name) y.post() seen.add(lib_name) # object has ancestors to process (shared libraries): add them to the end of the list if getattr(y, 'uselib_local', None): for x in self.to_list(getattr(y, 'uselib_local', [])): obj = get(x) obj.post() if getattr(obj, 'link_task', None): if not isinstance(obj.link_task, stlink_task): tmp.append(x) # link task and flags if getattr(y, 'link_task', None): link_name = y.target[y.target.rfind(os.sep) + 1:] if isinstance(y.link_task, stlink_task): env.append_value('STLIB', [link_name]) else: # some linkers can link against programs env.append_value('LIB', [link_name]) # the order self.link_task.set_run_after(y.link_task) # for the recompilation self.link_task.dep_nodes += y.link_task.outputs # add the link path too tmp_path = y.link_task.outputs[0].parent.bldpath() if not tmp_path in env['LIBPATH']: env.prepend_value('LIBPATH', [tmp_path]) # add ancestors uselib too - but only propagate those that have no staticlib defined for v in self.to_list(getattr(y, 'uselib', [])): if not env['STLIB_' + v]: if not v in self.uselib: self.uselib.insert(0, v) # if the library task generator provides 'export_includes', add to the include path # the export_includes must be a list of paths relative to the other library if getattr(y, 'export_includes', None): self.includes.extend(y.to_incnodes(y.export_includes)) @TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') @TaskGen.after('apply_link') def apply_objdeps(self): "add the .o files produced by some other object files in the same manner as uselib_local" names = getattr(self, 'add_objects', []) if not names: return names = self.to_list(names) get = self.bld.get_tgen_by_name seen = [] while names: x = names[0] # visit dependencies only once if x in seen: names = names[1:] continue # object does not exist ? y = get(x) # object has ancestors to process first ? update the list of names if getattr(y, 'add_objects', None): added = 0 lst = y.to_list(y.add_objects) lst.reverse() for u in lst: if u in seen: continue added = 1 names = [u]+names if added: continue # list of names modified, loop # safe to process the current object y.post() seen.append(x) for t in getattr(y, 'compiled_tasks', []): self.link_task.inputs.extend(t.outputs) @TaskGen.after('apply_link') def process_obj_files(self): if not hasattr(self, 'obj_files'): return for x in self.obj_files: node = self.path.find_resource(x) self.link_task.inputs.append(node) @TaskGen.taskgen_method def add_obj_file(self, file): """Small example on how to link object files as if they were source obj = bld.create_obj('cc') obj.add_obj_file('foo.o')""" if not hasattr(self, 'obj_files'): self.obj_files = [] if not 'process_obj_files' in self.meths: self.meths.append('process_obj_files') self.obj_files.append(file) old_define = Configure.ConfigurationContext.__dict__['define'] @Configure.conf def define(self, key, val, quote=True): old_define(self, key, val, quote) if key.startswith('HAVE_'): self.env[key] = 1 old_undefine = Configure.ConfigurationContext.__dict__['undefine'] @Configure.conf def undefine(self, key): old_undefine(self, key) if key.startswith('HAVE_'): self.env[key] = 0 # some people might want to use export_incdirs, but it was renamed def set_incdirs(self, val): Logs.warn('compat: change "export_incdirs" by "export_includes"') self.export_includes = val TaskGen.task_gen.export_incdirs = property(None, set_incdirs) debian/waf-1.6/waflib/extras/eclipse.py0000664000000000000000000002514412145744415015034 0ustar #! /usr/bin/env python # encoding: utf-8 # Eclipse CDT 5.0 generator for Waf # Richard Quirk 2009-1011 (New BSD License) # Thomas Nagy 2011 (ported to Waf 1.6) """ Usage: def options(opt): opt.load('eclipse') $ waf configure eclipse """ import sys, os from waflib import Utils, Logs, Context, Options, Build, TaskGen, Scripting from xml.dom.minidom import Document oe_cdt = 'org.eclipse.cdt' cdt_mk = oe_cdt + '.make.core' cdt_core = oe_cdt + '.core' cdt_bld = oe_cdt + '.build.core' class eclipse(Build.BuildContext): cmd = 'eclipse' fun = Scripting.default_cmd def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) self.create_cproject(appname, pythonpath=self.env['ECLIPSE_PYTHON_PATH']) def create_cproject(self, appname, workspace_includes=[], pythonpath=[]): """ Create the Eclipse CDT .project and .cproject files @param appname The name that will appear in the Project Explorer @param build The BuildContext object to extract includes from @param workspace_includes Optional project includes to prevent "Unresolved Inclusion" errors in the Eclipse editor @param pythonpath Optional project specific python paths """ source_dirs = [] cpppath = self.env['CPPPATH'] Logs.warn('Generating Eclipse CDT project files') for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue tg.post() if not getattr(tg, 'link_task', None): continue l = Utils.to_list(getattr(tg, "includes", '')) sources = Utils.to_list(getattr(tg, 'source', '')) features = Utils.to_list(getattr(tg, 'features', '')) is_cc = 'c' in features or 'cxx' in features bldpath = tg.path.bldpath() base = os.path.normpath(os.path.join(self.bldnode.name, tg.path.srcpath())) if is_cc: sources_dirs = set([src.parent for src in tg.to_nodes(sources)]) incnodes = tg.to_incnodes(tg.to_list(getattr(tg, 'includes', [])) + tg.env['INCLUDES']) for p in incnodes: path = p.path_from(self.srcnode) workspace_includes.append(path) if is_cc and path not in source_dirs: source_dirs.append(path) project = self.impl_create_project(sys.executable, appname) self.srcnode.make_node('.project').write(project.toprettyxml()) waf = os.path.abspath(sys.argv[0]) project = self.impl_create_cproject(sys.executable, waf, appname, workspace_includes, cpppath, source_dirs) self.srcnode.make_node('.cproject').write(project.toprettyxml()) project = self.impl_create_pydevproject(appname, sys.path, pythonpath) self.srcnode.make_node('.pydevproject').write(project.toprettyxml()) def impl_create_project(self, executable, appname): doc = Document() projectDescription = doc.createElement('projectDescription') self.add(doc, projectDescription, 'name', appname) self.add(doc, projectDescription, 'comment') self.add(doc, projectDescription, 'projects') buildSpec = self.add(doc, projectDescription, 'buildSpec') buildCommand = self.add(doc, buildSpec, 'buildCommand') self.add(doc, buildCommand, 'name', oe_cdt + '.managedbuilder.core.genmakebuilder') self.add(doc, buildCommand, 'triggers', 'clean,full,incremental,') arguments = self.add(doc, buildCommand, 'arguments') # the default make-style targets are overwritten by the .cproject values dictionaries = { cdt_mk + '.contents': cdt_mk + '.activeConfigSettings', cdt_mk + '.enableAutoBuild': 'false', cdt_mk + '.enableCleanBuild': 'true', cdt_mk + '.enableFullBuild': 'true', } for k, v in dictionaries.items(): self.addDictionary(doc, arguments, k, v) natures = self.add(doc, projectDescription, 'natures') nature_list = """ core.ccnature managedbuilder.core.ScannerConfigNature managedbuilder.core.managedBuildNature core.cnature """.split() for n in nature_list: self.add(doc, natures, 'nature', oe_cdt + '.' + n) self.add(doc, natures, 'nature', 'org.python.pydev.pythonNature') doc.appendChild(projectDescription) return doc def impl_create_cproject(self, executable, waf, appname, workspace_includes, cpppath, source_dirs=[]): doc = Document() doc.appendChild(doc.createProcessingInstruction('fileVersion', '4.0.0')) cconf_id = cdt_core + '.default.config.1' cproject = doc.createElement('cproject') storageModule = self.add(doc, cproject, 'storageModule', {'moduleId': cdt_core + '.settings'}) cconf = self.add(doc, storageModule, 'cconfiguration', {'id':cconf_id}) storageModule = self.add(doc, cconf, 'storageModule', {'buildSystemId': oe_cdt + '.managedbuilder.core.configurationDataProvider', 'id': cconf_id, 'moduleId': cdt_core + '.settings', 'name': 'Default'}) self.add(doc, storageModule, 'externalSettings') extensions = self.add(doc, storageModule, 'extensions') extension_list = """ VCErrorParser MakeErrorParser GCCErrorParser GASErrorParser GLDErrorParser """.split() ext = self.add(doc, extensions, 'extension', {'id': cdt_core + '.ELF', 'point':cdt_core + '.BinaryParser'}) for e in extension_list: ext = self.add(doc, extensions, 'extension', {'id': cdt_core + '.' + e, 'point':cdt_core + '.ErrorParser'}) storageModule = self.add(doc, cconf, 'storageModule', {'moduleId': 'cdtBuildSystem', 'version': '4.0.0'}) config = self.add(doc, storageModule, 'configuration', {'artifactName': appname, 'id': cconf_id, 'name': 'Default', 'parent': cdt_bld + '.prefbase.cfg'}) folderInfo = self.add(doc, config, 'folderInfo', {'id': cconf_id+'.', 'name': '/', 'resourcePath': ''}) toolChain = self.add(doc, folderInfo, 'toolChain', {'id': cdt_bld + '.prefbase.toolchain.1', 'name': 'No ToolChain', 'resourceTypeBasedDiscovery': 'false', 'superClass': cdt_bld + '.prefbase.toolchain'}) targetPlatform = self.add(doc, toolChain, 'targetPlatform', { 'binaryParser': 'org.eclipse.cdt.core.ELF', 'id': cdt_bld + '.prefbase.toolchain.1', 'name': ''}) waf_build = '"%s" %s'%(waf, eclipse.fun) waf_clean = '"%s" clean'%(waf) builder = self.add(doc, toolChain, 'builder', {'autoBuildTarget': waf_build, 'command': executable, 'enableAutoBuild': 'false', 'cleanBuildTarget': waf_clean, 'enableIncrementalBuild': 'true', 'id': cdt_bld + '.settings.default.builder.1', 'incrementalBuildTarget': waf_build, 'managedBuildOn': 'false', 'name': 'Gnu Make Builder', 'superClass': cdt_bld + '.settings.default.builder'}) for tool_name in ("Assembly", "GNU C++", "GNU C"): tool = self.add(doc, toolChain, 'tool', {'id': cdt_bld + '.settings.holder.1', 'name': tool_name, 'superClass': cdt_bld + '.settings.holder'}) if cpppath or workspace_includes: incpaths = cdt_bld + '.settings.holder.incpaths' option = self.add(doc, tool, 'option', {'id': incpaths+'.1', 'name': 'Include Paths', 'superClass': incpaths, 'valueType': 'includePath'}) for i in workspace_includes: self.add(doc, option, 'listOptionValue', {'builtIn': 'false', 'value': '"${workspace_loc:/%s/%s}"'%(appname, i)}) for i in cpppath: self.add(doc, option, 'listOptionValue', {'builtIn': 'false', 'value': '"%s"'%(i)}) if source_dirs: sourceEntries = self.add(doc, config, 'sourceEntries') for i in source_dirs: self.add(doc, sourceEntries, 'entry', {'excluding': i, 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind': 'sourcePath', 'name': ''}) self.add(doc, sourceEntries, 'entry', { 'flags': 'VALUE_WORKSPACE_PATH|RESOLVED', 'kind': 'sourcePath', 'name': i}) storageModule = self.add(doc, cconf, 'storageModule', {'moduleId': cdt_mk + '.buildtargets'}) buildTargets = self.add(doc, storageModule, 'buildTargets') def addTargetWrap(name, runAll): return self.addTarget(doc, buildTargets, executable, name, '"%s" %s'%(waf, name), runAll) addTargetWrap('configure', True) addTargetWrap('dist', False) addTargetWrap('install', False) addTargetWrap('check', False) storageModule = self.add(doc, cproject, 'storageModule', {'moduleId': 'cdtBuildSystem', 'version': '4.0.0'}) project = self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname}) doc.appendChild(cproject) return doc def impl_create_pydevproject(self, appname, system_path, user_path): # create a pydevproject file doc = Document() doc.appendChild(doc.createProcessingInstruction('eclipse-pydev', 'version="1.0"')) pydevproject = doc.createElement('pydev_project') prop = self.add(doc, pydevproject, 'pydev_property', 'python %d.%d'%(sys.version_info[0], sys.version_info[1])) prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_VERSION') prop = self.add(doc, pydevproject, 'pydev_property', 'Default') prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_INTERPRETER') # add waf's paths wafadmin = [p for p in system_path if p.find('wafadmin') != -1] if wafadmin: prop = self.add(doc, pydevproject, 'pydev_pathproperty', {'name':'org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH'}) for i in wafadmin: self.add(doc, prop, 'path', i) if user_path: prop = self.add(doc, pydevproject, 'pydev_pathproperty', {'name':'org.python.pydev.PROJECT_SOURCE_PATH'}) for i in user_path: self.add(doc, prop, 'path', '/'+appname+'/'+i) doc.appendChild(pydevproject) return doc def addDictionary(self, doc, parent, k, v): dictionary = self.add(doc, parent, 'dictionary') self.add(doc, dictionary, 'key', k) self.add(doc, dictionary, 'value', v) return dictionary def addTarget(self, doc, buildTargets, executable, name, buildTarget, runAllBuilders=True): target = self.add(doc, buildTargets, 'target', {'name': name, 'path': '', 'targetID': oe_cdt + '.build.MakeTargetBuilder'}) self.add(doc, target, 'buildCommand', executable) self.add(doc, target, 'buildArguments', None) self.add(doc, target, 'buildTarget', buildTarget) self.add(doc, target, 'stopOnError', 'true') self.add(doc, target, 'useDefaultCommand', 'false') self.add(doc, target, 'runAllBuilders', str(runAllBuilders).lower()) def add(self, doc, parent, tag, value = None): el = doc.createElement(tag) if (value): if type(value) == type(str()): el.appendChild(doc.createTextNode(value)) elif type(value) == type(dict()): self.setAttributes(el, value) parent.appendChild(el) return el def setAttributes(self, node, attrs): for k, v in attrs.items(): node.setAttribute(k, v) debian/waf-1.6/waflib/extras/objcopy.py0000664000000000000000000000332612145744415015053 0ustar #!/usr/bin/python # Grygoriy Fuchedzhy 2010 """ Support for converting linked targets to ihex, srec or binary files using objcopy. Use the 'objcopy' feature in conjuction with the 'cc' or 'cxx' feature. The 'objcopy' feature uses the following attributes: objcopy_bfdname Target object format name (eg. ihex, srec, binary). Defaults to ihex. objcopy_target File name used for objcopy output. This defaults to the target name with objcopy_bfdname as extension. objcopy_install_path Install path for objcopy_target file. Defaults to ${PREFIX}/fw. objcopy_flags Additional flags passed to objcopy. """ from waflib.Utils import def_attrs from waflib import Task from waflib.TaskGen import feature, after_method class objcopy(Task.Task): run_str = '${OBJCOPY} -O ${TARGET_BFDNAME} ${OBJCOPYFLAGS} ${SRC} ${TGT}' color = 'CYAN' @feature('objcopy') @after_method('apply_link') def objcopy(self): def_attrs(self, objcopy_bfdname = 'ihex', objcopy_target = None, objcopy_install_path = "${PREFIX}/firmware", objcopy_flags = '') link_output = self.link_task.outputs[0] if not self.objcopy_target: self.objcopy_target = link_output.change_ext('.' + self.objcopy_bfdname).name task = self.create_task('objcopy', src=link_output, tgt=self.path.find_or_declare(self.objcopy_target)) task.env.append_unique('TARGET_BFDNAME', self.objcopy_bfdname) try: task.env.append_unique('OBJCOPYFLAGS', getattr(self, 'objcopy_flags')) except AttributeError: pass if self.objcopy_install_path: self.bld.install_files(self.objcopy_install_path, task.outputs[0], env=task.env.derive()) def configure(ctx): objcopy = ctx.find_program('objcopy', var='OBJCOPY', mandatory=True) debian/waf-1.6/waflib/extras/sync_exec.py0000664000000000000000000000141112145744415015357 0ustar #! /usr/bin/env python # encoding: utf-8 """ Force the execution output to be synchronized May deadlock with a lot of output (subprocess limitation) """ import sys from waflib.Build import BuildContext from waflib import Utils, Logs def exec_command(self, cmd, **kw): subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) Logs.debug('runner: %r' % cmd) Logs.debug('runner_env: kw=%s' % kw) try: kw['stdout'] = kw['stderr'] = subprocess.PIPE p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() if out: sys.stdout.write(out.decode(sys.stdout.encoding or 'iso8859-1')) if err: sys.stdout.write(err.decode(sys.stdout.encoding or 'iso8859-1')) return p.returncode except OSError: return -1 BuildContext.exec_command = exec_command debian/waf-1.6/waflib/extras/go.py0000664000000000000000000001753512145744415014022 0ustar #!/usr/bin/env python # encoding: utf-8 # Tom Wambold tom5760 gmail.com 2009 # Thomas Nagy 2010 """ Go as a language may look nice, but its toolchain is one of the worse a developer has ever seen. It keeps changing though, and I would like to believe that it will get better eventually, but the crude reality is that this tool and the examples are getting broken every few months. If you have been lured into trying to use Go, you should stick to their Makefiles. """ import os, platform from waflib import Utils, Task, TaskGen from waflib.TaskGen import feature, extension, after_method, before_method from waflib.Tools.ccroot import link_task, stlink_task, propagate_uselib_vars, process_use class go(Task.Task): run_str = '${GOC} ${GOCFLAGS} ${CPPPATH_ST:INCPATHS} -o ${TGT} ${SRC}' class gopackage(stlink_task): run_str = '${GOP} grc ${TGT} ${SRC}' class goprogram(link_task): run_str = '${GOL} ${GOLFLAGS} -o ${TGT} ${SRC}' inst_to = '${BINDIR}' chmod = Utils.O755 class cgopackage(stlink_task): color = 'YELLOW' inst_to = '${LIBDIR}' ext_in = ['.go'] ext_out = ['.a'] def run(self): src_dir = self.generator.bld.path source = self.inputs target = self.outputs[0].change_ext('') #print ("--> %s" % self.outputs) #print ('++> %s' % self.outputs[1]) bld_dir = self.outputs[1] bld_dir.mkdir() obj_dir = bld_dir.make_node('_obj') obj_dir.mkdir() bld_srcs = [] for s in source: # FIXME: it seems gomake/cgo stumbles on filenames like a/b/c.go # -> for the time being replace '/' with '_'... #b = bld_dir.make_node(s.path_from(src_dir)) b = bld_dir.make_node(s.path_from(src_dir).replace(os.sep,'_')) b.parent.mkdir() #print ('++> %s' % (s.path_from(src_dir),)) try: try:os.remove(b.abspath()) except Exception:pass os.symlink(s.abspath(), b.abspath()) except Exception: # if no support for symlinks, copy the file from src b.write(s.read()) bld_srcs.append(b) #print("--|> [%s]" % b.abspath()) b.sig = Utils.h_file(b.abspath()) pass #self.set_inputs(bld_srcs) #self.generator.bld.raw_deps[self.uid()] = [self.signature()] + bld_srcs makefile_node = bld_dir.make_node("Makefile") makefile_tmpl = '''\ # Copyright 2009 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. --- include $(GOROOT)/src/Make.inc TARG=%(target)s GCIMPORTS= %(gcimports)s CGOFILES=\\ \t%(source)s CGO_CFLAGS= %(cgo_cflags)s CGO_LDFLAGS= %(cgo_ldflags)s include $(GOROOT)/src/Make.pkg %%: install %%.go $(GC) $*.go $(LD) -o $@ $*.$O ''' % { 'gcimports': ' '.join(l for l in self.env['GOCFLAGS']), 'cgo_cflags' : ' '.join(l for l in self.env['GOCFLAGS']), 'cgo_ldflags': ' '.join(l for l in self.env['GOLFLAGS']), 'target': target.path_from(obj_dir), 'source': ' '.join([b.path_from(bld_dir) for b in bld_srcs]) } makefile_node.write(makefile_tmpl) #print ("::makefile: %s"%makefile_node.abspath()) cmd = Utils.subst_vars('gomake ${GOMAKE_FLAGS}', self.env).strip() o = self.outputs[0].change_ext('.gomake.log') fout_node = bld_dir.find_or_declare(o.name) fout = open(fout_node.abspath(), 'w') rc = self.generator.bld.exec_command( cmd, stdout=fout, stderr=fout, cwd=bld_dir.abspath(), ) if rc != 0: import waflib.Logs as msg msg.error('** error running [%s] (cgo-%s)' % (cmd, target)) msg.error(fout_node.read()) return rc self.generator.bld.read_stlib( target, paths=[obj_dir.abspath(),], ) tgt = self.outputs[0] if tgt.parent != obj_dir: install_dir = os.path.join('${LIBDIR}', tgt.parent.path_from(obj_dir)) else: install_dir = '${LIBDIR}' #print('===> %s (%s)' % (tgt.abspath(), install_dir)) self.generator.bld.install_files( install_dir, tgt.abspath(), relative_trick=False, postpone=False, ) return rc @extension('.go') def compile_go(self, node): #print('*'*80, self.name) if not ('cgopackage' in self.features): return self.create_compiled_task('go', node) #print ('compile_go-cgo...') bld_dir = node.parent.get_bld() obj_dir = bld_dir.make_node('_obj') target = obj_dir.make_node(node.change_ext('.a').name) return self.create_task('cgopackage', node, node.change_ext('.a')) @feature('gopackage', 'goprogram', 'cgopackage') @before_method('process_source') def go_compiler_is_foobar(self): if self.env.GONAME == 'gcc': return self.source = self.to_nodes(self.source) src = [] go = [] for node in self.source: if node.name.endswith('.go'): go.append(node) else: src.append(node) self.source = src if not ('cgopackage' in self.features): #print('--> [%s]... (%s)' % (go[0], getattr(self, 'target', 'N/A'))) tsk = self.create_compiled_task('go', go[0]) tsk.inputs.extend(go[1:]) else: #print ('+++ [%s] +++' % self.target) bld_dir = self.path.get_bld().make_node('cgopackage--%s' % self.target.replace(os.sep,'_')) obj_dir = bld_dir.make_node('_obj') target = obj_dir.make_node(self.target+'.a') tsk = self.create_task('cgopackage', go, [target, bld_dir]) self.link_task = tsk @feature('gopackage', 'goprogram', 'cgopackage') @after_method('process_source', 'apply_incpaths',) def go_local_libs(self): names = self.to_list(getattr(self, 'use', [])) #print ('== go-local-libs == [%s] == use: %s' % (self.name, names)) for name in names: tg = self.bld.get_tgen_by_name(name) if not tg: raise Utils.WafError('no target of name %r necessary for %r in go uselib local' % (name, self)) tg.post() #print ("-- tg[%s]: %s" % (self.name,name)) lnk_task = getattr(tg, 'link_task', None) if lnk_task: for tsk in self.tasks: if isinstance(tsk, (go, gopackage, cgopackage)): tsk.set_run_after(lnk_task) tsk.dep_nodes.extend(lnk_task.outputs) path = lnk_task.outputs[0].parent.abspath() if isinstance(lnk_task, (go, gopackage)): # handle hierarchical packages path = lnk_task.generator.path.get_bld().abspath() elif isinstance(lnk_task, (cgopackage,)): # handle hierarchical cgopackages cgo_obj_dir = lnk_task.outputs[1].find_or_declare('_obj') path = cgo_obj_dir.abspath() # recursively add parent GOCFLAGS... self.env.append_unique('GOCFLAGS', getattr(lnk_task.env, 'GOCFLAGS',[])) # ditto for GOLFLAGS... self.env.append_unique('GOLFLAGS', getattr(lnk_task.env, 'GOLFLAGS',[])) self.env.append_unique('GOCFLAGS', ['-I%s' % path]) self.env.append_unique('GOLFLAGS', ['-L%s' % path]) for n in getattr(tg, 'includes_nodes', []): self.env.append_unique('GOCFLAGS', ['-I%s' % n.abspath()]) pass pass def configure(conf): def set_def(var, val): if not conf.env[var]: conf.env[var] = val goarch = os.getenv('GOARCH') if goarch == '386': set_def('GO_PLATFORM', 'i386') elif goarch == 'amd64': set_def('GO_PLATFORM', 'x86_64') elif goarch == 'arm': set_def('GO_PLATFORM', 'arm') else: set_def('GO_PLATFORM', platform.machine()) if conf.env.GO_PLATFORM == 'x86_64': set_def('GO_COMPILER', '6g') set_def('GO_LINKER', '6l') elif conf.env.GO_PLATFORM in ['i386', 'i486', 'i586', 'i686']: set_def('GO_COMPILER', '8g') set_def('GO_LINKER', '8l') elif conf.env.GO_PLATFORM == 'arm': set_def('GO_COMPILER', '5g') set_def('GO_LINKER', '5l') set_def('GO_EXTENSION', '.5') if not (conf.env.GO_COMPILER or conf.env.GO_LINKER): raise conf.fatal('Unsupported platform ' + platform.machine()) set_def('GO_PACK', 'gopack') set_def('gopackage_PATTERN', '%s.a') set_def('CPPPATH_ST', '-I%s') set_def('GOMAKE_FLAGS', ['--quiet']) conf.find_program(conf.env.GO_COMPILER, var='GOC') conf.find_program(conf.env.GO_LINKER, var='GOL') conf.find_program(conf.env.GO_PACK, var='GOP') conf.find_program('cgo', var='CGO') TaskGen.feature('go')(process_use) TaskGen.feature('go')(propagate_uselib_vars) debian/waf-1.6/waflib/extras/boost.py0000664000000000000000000002667212145744415014545 0ustar #!/usr/bin/env python # encoding: utf-8 # # partially based on boost.py written by Gernot Vormayr # written by Ruediger Sonderfeld , 2008 # modified by Bjoern Michaelsen, 2008 # modified by Luca Fossati, 2008 # rewritten for waf 1.5.1, Thomas Nagy, 2008 # rewritten for waf 1.6.2, Sylvain Rouquette, 2011 ''' This is an extra tool, not bundled with the default waf binary. To add the boost tool to the waf file: $ ./waf-light --tools=compat15,boost or, if you have waf >= 1.6.2 $ ./waf update --files=boost When using this tool, the wscript will look like: def options(opt): opt.load('compiler_cxx boost') def configure(conf): conf.load('compiler_cxx boost') conf.check_boost(lib='system filesystem') def build(bld): bld(source='main.cpp', target='app', use='BOOST') Options are generated, in order to specify the location of boost includes/libraries. The `check_boost` configuration function allows to specify the used boost libraries. It can also provide default arguments to the --boost-static and --boost-mt command-line arguments. Everything will be packaged together in a BOOST component that you can use. When using MSVC, a lot of compilation flags need to match your BOOST build configuration: - you may have to add /EHsc to your CXXFLAGS or define boost::throw_exception if BOOST_NO_EXCEPTIONS is defined. Errors: C4530 - boost libraries will try to be smart and use the (pretty but often not useful) auto-linking feature of MSVC So before calling `conf.check_boost` you might want to disabling by adding: conf.env.DEFINES_BOOST += ['BOOST_ALL_NO_LIB'] Errors: - boost might also be compiled with /MT, which links the runtime statically. If you have problems with redefined symbols, self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] self.env['CXXFLAGS_%s' % var] += ['/MD', '/EHsc'] Passing `--boost-linkage_autodetect` might help ensuring having a correct linkage in some basic cases. ''' import sys import re from waflib import Utils, Logs, Errors from waflib.Configure import conf BOOST_LIBS = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/sw/lib', '/lib'] BOOST_INCLUDES = ['/usr/include', '/usr/local/include', '/opt/local/include', '/sw/include'] BOOST_VERSION_FILE = 'boost/version.hpp' BOOST_VERSION_CODE = ''' #include #include int main() { std::cout << BOOST_LIB_VERSION << std::endl; } ''' # toolsets from {boost_dir}/tools/build/v2/tools/common.jam PLATFORM = Utils.unversioned_sys_platform() detect_intel = lambda env: (PLATFORM == 'win32') and 'iw' or 'il' detect_clang = lambda env: (PLATFORM == 'darwin') and 'clang-darwin' or 'clang' detect_mingw = lambda env: (re.search('MinGW', env.CXX[0])) and 'mgw' or 'gcc' BOOST_TOOLSETS = { 'borland': 'bcb', 'clang': detect_clang, 'como': 'como', 'cw': 'cw', 'darwin': 'xgcc', 'edg': 'edg', 'g++': detect_mingw, 'gcc': detect_mingw, 'icpc': detect_intel, 'intel': detect_intel, 'kcc': 'kcc', 'kylix': 'bck', 'mipspro': 'mp', 'mingw': 'mgw', 'msvc': 'vc', 'qcc': 'qcc', 'sun': 'sw', 'sunc++': 'sw', 'tru64cxx': 'tru', 'vacpp': 'xlc' } def options(opt): opt.add_option('--boost-includes', type='string', default='', dest='boost_includes', help='''path to the boost includes root (~boost root) e.g. /path/to/boost_1_47_0''') opt.add_option('--boost-libs', type='string', default='', dest='boost_libs', help='''path to the directory where the boost libs are e.g. /path/to/boost_1_47_0/stage/lib''') opt.add_option('--boost-static', action='store_true', default=False, dest='boost_static', help='link with static boost libraries (.lib/.a)') opt.add_option('--boost-mt', action='store_true', default=False, dest='boost_mt', help='select multi-threaded libraries') opt.add_option('--boost-abi', type='string', default='', dest='boost_abi', help='''select libraries with tags (dgsyp, d for debug), see doc Boost, Getting Started, chapter 6.1''') opt.add_option('--boost-linkage_autodetect', action="store_true", dest='boost_linkage_autodetect', help="auto-detect boost linkage options (don't get used to it / might break other stuff)") opt.add_option('--boost-toolset', type='string', default='', dest='boost_toolset', help='force a toolset e.g. msvc, vc90, \ gcc, mingw, mgw45 (default: auto)') py_version = '%d%d' % (sys.version_info[0], sys.version_info[1]) opt.add_option('--boost-python', type='string', default=py_version, dest='boost_python', help='select the lib python with this version \ (default: %s)' % py_version) @conf def __boost_get_version_file(self, dir): try: return self.root.find_dir(dir).find_node(BOOST_VERSION_FILE) except: return None @conf def boost_get_version(self, dir): """silently retrieve the boost version number""" re_but = re.compile('^#define\\s+BOOST_LIB_VERSION\\s+"(.*)"$', re.M) try: val = re_but.search(self.__boost_get_version_file(dir).read()).group(1) except: val = self.check_cxx(fragment=BOOST_VERSION_CODE, includes=[dir], execute=False, define_ret=True) return val @conf def boost_get_includes(self, *k, **kw): includes = k and k[0] or kw.get('includes', None) if includes and self.__boost_get_version_file(includes): return includes for dir in BOOST_INCLUDES: if self.__boost_get_version_file(dir): return dir if includes: self.fatal('headers not found in %s' % includes) else: self.fatal('headers not found, please provide a --boost-includes argument (see help)') @conf def boost_get_toolset(self, cc): toolset = cc if not cc: build_platform = Utils.unversioned_sys_platform() if build_platform in BOOST_TOOLSETS: cc = build_platform else: cc = self.env.CXX_NAME if cc in BOOST_TOOLSETS: toolset = BOOST_TOOLSETS[cc] return isinstance(toolset, str) and toolset or toolset(self.env) @conf def __boost_get_libs_path(self, *k, **kw): ''' return the lib path and all the files in it ''' if 'files' in kw: return self.root.find_dir('.'), Utils.to_list(kw['files']) libs = k and k[0] or kw.get('libs', None) if libs: path = self.root.find_dir(libs) files = path.ant_glob('*boost_*') if not libs or not files: for dir in BOOST_LIBS: try: path = self.root.find_dir(dir) files = path.ant_glob('*boost_*') if files: break path = self.root.find_dir(dir + '64') files = path.ant_glob('*boost_*') if files: break except: path = None if not path: if libs: self.fatal('libs not found in %s' % libs) else: self.fatal('libs not found, please provide a --boost-libs argument (see help)') self.to_log('Found the boost path in %r with the libraries:' % path) for x in files: self.to_log(' %r' % x) return path, files @conf def boost_get_libs(self, *k, **kw): ''' return the lib path and the required libs according to the parameters ''' path, files = self.__boost_get_libs_path(**kw) t = [] if kw.get('mt', False): t.append('mt') if kw.get('abi', None): t.append(kw['abi']) tags = t and '(-%s)+' % '-'.join(t) or '' toolset = self.boost_get_toolset(kw.get('toolset', '')) toolset_pat = '(-%s[0-9]{0,3})+' % toolset version = '(-%s)+' % self.env.BOOST_VERSION def find_lib(re_lib, files): for file in files: if re_lib.search(file.name): self.to_log('Found boost lib %s' % file) return file return None def format_lib_name(name): if name.startswith('lib'): name = name[3:] return name.split('.')[0] libs = [] for lib in Utils.to_list(k and k[0] or kw.get('lib', None)): py = (lib == 'python') and '(-py%s)+' % kw['python'] or '' # Trying libraries, from most strict match to least one for pattern in ['boost_%s%s%s%s%s' % (lib, toolset_pat, tags, py, version), 'boost_%s%s%s%s' % (lib, tags, py, version), 'boost_%s%s%s' % (lib, tags, version), # Give up trying to find the right version 'boost_%s%s%s%s' % (lib, toolset_pat, tags, py), 'boost_%s%s%s' % (lib, tags, py), 'boost_%s%s' % (lib, tags)]: self.to_log('Trying pattern %s' % pattern) file = find_lib(re.compile(pattern), files) if file: libs.append(format_lib_name(file.name)) break else: self.fatal('lib %s not found in %s' % (lib, path.abspath())) return path.abspath(), libs @conf def check_boost(self, *k, **kw): """ Initialize boost libraries to be used. Keywords: you can pass the same parameters as with the command line (without "--boost-"). Note that the command line has the priority, and should preferably be used. """ if not self.env['CXX']: self.fatal('load a c++ compiler first, conf.load("compiler_cxx")') params = {'lib': k and k[0] or kw.get('lib', None)} for key, value in self.options.__dict__.items(): if not key.startswith('boost_'): continue key = key[len('boost_'):] params[key] = value and value or kw.get(key, '') var = kw.get('uselib_store', 'BOOST') self.start_msg('Checking boost includes') self.env['INCLUDES_%s' % var] = inc = self.boost_get_includes(**params) self.env.BOOST_VERSION = self.boost_get_version(inc) self.end_msg(self.env.BOOST_VERSION) if Logs.verbose: Logs.pprint('CYAN', ' path : %s' % self.env['INCLUDES_%s' % var]) if not params['lib']: return self.start_msg('Checking boost libs') suffix = params.get('static', None) and 'ST' or '' path, libs = self.boost_get_libs(**params) self.env['%sLIBPATH_%s' % (suffix, var)] = [path] self.env['%sLIB_%s' % (suffix, var)] = libs self.end_msg('ok') if Logs.verbose: Logs.pprint('CYAN', ' path : %s' % path) Logs.pprint('CYAN', ' libs : %s' % libs) def try_link(): if 'system' in params['lib']: self.check_cxx( fragment="\n".join([ '#include ', 'int main() { boost::system::error_code c; }', ]), use=var, execute=False, ) if 'thread' in params['lib']: self.check_cxx( fragment="\n".join([ '#include ', 'int main() { boost::thread t; }', ]), use=var, execute=False, ) if params.get('linkage_autodetect', False): self.start_msg("Attempting to detect boost linkage flags") toolset = self.boost_get_toolset(kw.get('toolset', '')) if toolset in ['vc']: # disable auto-linking feature, causing error LNK1181 # because the code wants to be linked against self.env['DEFINES_%s' % var] += ['BOOST_ALL_NO_LIB'] # if no dlls are present, we guess the .lib files are not stubs has_dlls = False for x in Utils.listdir(path): if x.endswith(self.env.cxxshlib_PATTERN % ''): has_dlls = True break if not has_dlls: self.env['STLIBPATH_%s' % var] = [path] self.env['STLIB_%s' % var] = libs del self.env['LIB_%s' % var] del self.env['LIBPATH_%s' % var] # we attempt to play with some known-to-work CXXFLAGS combinations for cxxflags in (['/MD', '/EHsc'], []): self.env.stash() self.env["CXXFLAGS_%s" % var] += cxxflags try: try_link() self.end_msg("ok: winning cxxflags combination: %s" % (self.env["CXXFLAGS_%s" % var])) e = None break except Errors.ConfigurationError as exc: self.env.revert() e = exc if e is not None: self.fatal("Could not auto-detect boost linking flags combination, you may report it to boost.py author", ex=e) else: self.fatal("Boost linkage flags auto-detection not implemented (needed ?) for this toolchain") else: self.start_msg('Checking for boost linkage') try: try_link() except Errors.ConfigurationError as e: self.fatal("Could not link against boost libraries using supplied options") self.end_msg('ok') debian/waf-1.6/waflib/extras/erlang.py0000664000000000000000000000055312145744415014655 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Erlang support """ from waflib import TaskGen TaskGen.declare_chain(name = 'erlc', rule = '${ERLC} ${ERLC_FLAGS} ${SRC[0].abspath()} -o ${TGT[0].name}', ext_in = '.erl', ext_out = '.beam') def configure(conf): conf.find_program('erlc', var='ERLC') conf.env.ERLC_FLAGS = [] debian/waf-1.6/waflib/extras/package.py0000664000000000000000000000307012145744415014775 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 """ Obtain packages, unpack them in a location, and add associated uselib variables (CFLAGS_pkgname, LIBPATH_pkgname, etc). The default is use a Dependencies.txt file in the source directory. This is a work in progress. Usage: def options(opt): opt.load('package') def configure(conf): conf.load_packages() """ from waflib import Logs from waflib.Configure import conf try: from urllib import request except: from urllib import urlopen else: urlopen = request.urlopen CACHEVAR = 'WAFCACHE_PACKAGE' @conf def get_package_cache_dir(self): cache = None if CACHEVAR in conf.environ: cache = conf.environ[CACHEVAR] cache = self.root.make_node(cache) elif self.env[CACHEVAR]: cache = self.env[CACHEVAR] cache = self.root.make_node(cache) else: cache = self.srcnode.make_node('.wafcache_package') cache.mkdir() return cache @conf def download_archive(self, src, dst): for x in self.env.PACKAGE_REPO: url = '/'.join((x, src)) try: web = urlopen(url) try: if web.getcode() != 200: continue except AttributeError: pass except Exception: # on python3 urlopen throws an exception # python 2.3 does not have getcode and throws an exception to fail continue else: tmp = self.root.make_node(dst) tmp.write(web.read()) Logs.warn('Downloaded %s from %s' % (tmp.abspath(), url)) break else: self.fatal('Could not get the package %s' % src) @conf def load_packages(self): cache = self.get_package_cache_dir() # read the dependencies, get the archives, .. debian/waf-1.6/waflib/extras/dcc.py0000664000000000000000000000414012145744415014132 0ustar #!/usr/bin/env python # encoding: utf-8 # Jérôme Carretero, 2011 (zougloub) from waflib import Configure, Options, Utils from waflib.Tools import ccroot from waflib.Configure import conf @conf def find_dcc(conf): cc = conf.find_program(['dcc'], var='CC', path_list=getattr(Options.options, 'diabbindir', "")) cc = conf.cmd_to_list(cc) conf.env.CC_NAME = 'dcc' conf.env.CC = cc @conf def find_dld(conf): ld = conf.find_program(['dld'], var='LINK_CC', path_list=getattr(Options.options, 'diabbindir', "")) ld = conf.cmd_to_list(ld) conf.env.LINK_CC_NAME = 'dld' conf.env.LINK_CC = ld @conf def find_dar(conf): ar = conf.find_program(['dar'], var='DAR', path_list=getattr(Options.options, 'diabbindir', "")) ar = conf.cmd_to_list(ar) conf.env.AR = ar conf.env.AR_NAME = 'dar' conf.env.ARFLAGS = 'rcs' @conf def find_ddump(conf): prg = conf.find_program(['ddump'], var='DDUMP', path_list=getattr(Options.options, 'diabbindir', "")) prg = conf.cmd_to_list(prg) conf.env.DDUMP = prg @conf def dcc_common_flags(conf): v = conf.env v['CC_SRC_F'] = [] v['CC_TGT_F'] = ['-c', '-o'] # linker if not v['LINK_CC']: v['LINK_CC'] = v['CC'] v['CCLNK_SRC_F'] = [] v['CCLNK_TGT_F'] = ['-o'] v['CPPPATH_ST'] = '-I%s' v['DEFINES_ST'] = '-D%s' v['LIB_ST'] = '-l:%s' # template for adding libs v['LIBPATH_ST'] = '-L%s' # template for adding libpaths v['STLIB_ST'] = '-l:%s' v['STLIBPATH_ST'] = '-L%s' v['RPATH_ST'] = '-Wl,-rpath,%s' #v['STLIB_MARKER'] = '-Wl,-Bstatic' # program v['cprogram_PATTERN'] = '%s.elf' # static lib v['LINKFLAGS_cstlib'] = ['-Wl,-Bstatic'] v['cstlib_PATTERN'] = 'lib%s.a' def configure(conf): conf.find_dcc() conf.find_dar() conf.find_dld() conf.find_ddump() conf.dcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() def options(opt): """ Add the ``--with-diab-bindir`` command-line options. """ opt.add_option('--with-diab-bindir', type='string', dest='diabbindir', help = 'Specify alternate diab bin folder', default="") debian/waf-1.6/waflib/extras/proc.py0000664000000000000000000000340512145744415014347 0ustar #! /usr/bin/env python # per rosengren 2011 from os import environ, path from waflib import TaskGen, Utils def options(opt): grp = opt.add_option_group('Oracle ProC Options') grp.add_option('--oracle_home', action='store', default=environ.get('PROC_ORACLE'), help='Path to Oracle installation home (has bin/lib)') grp.add_option('--tns_admin', action='store', default=environ.get('TNS_ADMIN'), help='Directory containing server list (TNS_NAMES.ORA)') grp.add_option('--connection', action='store', default='dummy-user/dummy-password@dummy-server', help='Format: user/password@server') def configure(cnf): env = cnf.env if not env.PROC_ORACLE: env.PROC_ORACLE = cnf.options.oracle_home if not env.PROC_TNS_ADMIN: env.PROC_TNS_ADMIN = cnf.options.tns_admin if not env.PROC_CONNECTION: env.PROC_CONNECTION = cnf.options.connection cnf.find_program('proc', var='PROC', path_list=env.PROC_ORACLE + path.sep + 'bin') def proc(tsk): env = tsk.env gen = tsk.generator bld = gen.bld inc_nodes = gen.to_incnodes(Utils.to_list(getattr(gen,'includes',[])) + env['INCLUDES']) # FIXME the if-else construct will not work in python 2 cmd = ( [env.PROC] + ['SQLCHECK=SEMANTICS'] + (['SYS_INCLUDE=(' + ','.join(env.PROC_INCLUDES) + ')'] if env.PROC_INCLUDES else []) + ['INCLUDE=(' + ','.join( [i.bldpath() for i in inc_nodes] ) + ')'] + ['userid=' + env.PROC_CONNECTION] + ['INAME=' + tsk.inputs[0].bldpath()] + ['ONAME=' + tsk.outputs[0].bldpath()] ) exec_env = { 'ORACLE_HOME': env.PROC_ORACLE, 'LD_LIBRARY_PATH': env.PROC_ORACLE + path.sep + 'lib', } if env.PROC_TNS_ADMIN: exec_env['TNS_ADMIN'] = env.PROC_TNS_ADMIN return tsk.exec_command(cmd, env=exec_env) TaskGen.declare_chain( name = 'proc', rule = proc, ext_in = '.pc', ext_out = '.c', ) debian/waf-1.6/waflib/extras/c_dumbpreproc.py0000664000000000000000000000272312145744415016232 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Dumb C/C++ preprocessor for finding dependencies It will look at all include files it can find after removing the comments, so the following will always add the dependency on both "a.h" and "b.h":: #include "a.h" #ifdef B #include "b.h" #endif int main() { return 0; } To use:: def configure(conf): conf.load('compiler_c') conf.load('c_dumbpreproc') """ import re, sys, os, string, traceback from waflib import Logs, Build, Utils, Errors from waflib.Logs import debug, error from waflib.Tools import c_preproc re_inc = re.compile( '^[ \t]*(#|%:)[ \t]*(include)[ \t]*[<"](.*)[>"]\r*$', re.IGNORECASE | re.MULTILINE) def lines_includes(node): code = node.read() if c_preproc.use_trigraphs: for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] parser = c_preproc.c_parser class dumb_parser(parser): def addlines(self, node): if node in self.nodes[:-1]: return self.currentnode_stack.append(node.parent) self.lines = lines_includes(node) + [(c_preproc.POPFILE, '')] + self.lines def start(self, node, env): self.addlines(node) while self.lines: (x, y) = self.lines.pop(0) if x == c_preproc.POPFILE: self.currentnode_stack.pop() continue self.tryfind(y) c_preproc.c_parser = dumb_parser debian/waf-1.6/waflib/extras/pgicxx.py0000664000000000000000000000067412145744415014713 0ustar #!/usr/bin/env python # encoding: utf-8 # Antoine Dechaume 2011 """ Detect the PGI C++ compiler """ import sys, re from waflib.Configure import conf from waflib.Tools.compiler_cxx import cxx_compiler cxx_compiler['linux'].append('pgicxx') from waflib.extras import pgicc def configure(conf): conf.find_pgi_compiler('CXX', 'pgCC') conf.find_ar() conf.gxx_common_flags() conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/extras/valadoc.py0000664000000000000000000000656612145744415015030 0ustar #! /usr/bin/env python # encoding: UTF-8 # Nicolas Joseph 2009 """ ported from waf 1.5: TODO: tabs vs spaces """ from waflib import Task, Utils, Node, Errors from waflib.TaskGen import feature, extension, after_method from Logs import debug, warn, error VALADOC_STR = '${VALADOC}' class valadoc(Task.Task): vars = ['VALADOC', 'VALADOCFLAGS'] color = 'BLUE' after = ['cprogram', 'cstlib', 'cshlib', 'cxxprogram', 'cxxstlib', 'cxxshlib'] quiet = True # no outputs .. this is weird def __init__(self, *k, **kw): Task.Task.__init__(*k, **kw) self.output_dir = '' self.doclet = '' self.package_name = '' self.package_version = '' self.files = [] self.protected = True self.private = False self.inherit = False self.deps = False self.enable_non_null_experimental = False self.force = False def run(self): if not self.env['VALADOCFLAGS']: self.env['VALADOCFLAGS'] = '' cmd = [Utils.subst_vars(VALADOC_STR, self.env)] cmd.append ('-o %s' % self.output_dir) if getattr(self, 'doclet', None): cmd.append ('--doclet %s' % self.doclet) cmd.append ('--package-name %s' % self.package_name) if getattr(self, 'version', None): cmd.append ('--package-version %s' % self.package_version) if getattr(self, 'packages', None): for package in self.packages: cmd.append ('--pkg %s' % package) if getattr(self, 'vapi_dirs', None): for vapi_dir in self.vapi_dirs: cmd.append ('--vapidir %s' % vapi_dir) if not getattr(self, 'protected', None): cmd.append ('--no-protected') if getattr(self, 'private', None): cmd.append ('--private') if getattr(self, 'inherit', None): cmd.append ('--inherit') if getattr(self, 'deps', None): cmd.append ('--deps') if getattr(self, 'enable_non_null_experimental', None): cmd.append ('--enable-non-null-experimental') if getattr(self, 'force', None): cmd.append ('--force') cmd.append (' '.join ([x.relpath_gen (self.generator.bld.bldnode) for x in self.files])) return self.generator.bld.exec_command(' '.join(cmd)) @feature('valadoc') def process_valadoc(self): task = self.create_task('valadoc') if getattr(self, 'output_dir', None): task.output_dir = self.output_dir else: Errors.WafError('no output directory') if getattr(self, 'doclet', None): task.doclet = self.doclet else: Errors.WafError('no doclet directory') if getattr(self, 'package_name', None): task.package_name = self.package_name else: Errors.WafError('no package name') if getattr(self, 'package_version', None): task.package_version = self.package_version if getattr(self, 'packages', None): task.packages = Utils.to_list(self.packages) if getattr(self, 'vapi_dirs', None): task.vapi_dirs = Utils.to_list(self.vapi_dirs) if getattr(self, 'files', None): task.files = self.files else: Errors.WafError('no input file') if getattr(self, 'protected', None): task.protected = self.protected if getattr(self, 'private', None): task.private = self.private if getattr(self, 'inherit', None): task.inherit = self.inherit if getattr(self, 'deps', None): task.deps = self.deps if getattr(self, 'enable_non_null_experimental', None): task.enable_non_null_experimental = self.enable_non_null_experimental if getattr(self, 'force', None): task.force = self.force def configure(conf): conf.find_program('valadoc', errmsg='You must install valadoc for generate the API documentation') debian/waf-1.6/waflib/extras/ocaml.py0000664000000000000000000002242512145744415014502 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) "ocaml support" import os, re from waflib import TaskGen, Utils, Task, Build from waflib.Logs import error from waflib.TaskGen import feature, before_method, after_method, extension EXT_MLL = ['.mll'] EXT_MLY = ['.mly'] EXT_MLI = ['.mli'] EXT_MLC = ['.c'] EXT_ML = ['.ml'] open_re = re.compile('^\s*open\s+([a-zA-Z]+)(;;){0,1}$', re.M) foo = re.compile(r"""(\(\*)|(\*\))|("(\\.|[^"\\])*"|'(\\.|[^'\\])*'|.[^()*"'\\]*)""", re.M) def filter_comments(txt): meh = [0] def repl(m): if m.group(1): meh[0] += 1 elif m.group(2): meh[0] -= 1 elif not meh[0]: return m.group(0) return '' return foo.sub(repl, txt) def scan(self): node = self.inputs[0] code = filter_comments(node.read()) global open_re names = [] import_iterator = open_re.finditer(code) if import_iterator: for import_match in import_iterator: names.append(import_match.group(1)) found_lst = [] raw_lst = [] for name in names: nd = None for x in self.incpaths: nd = x.find_resource(name.lower()+'.ml') if not nd: nd = x.find_resource(name+'.ml') if nd: found_lst.append(nd) break else: raw_lst.append(name) return (found_lst, raw_lst) native_lst=['native', 'all', 'c_object'] bytecode_lst=['bytecode', 'all'] @feature('ocaml') def init_ml(self): Utils.def_attrs(self, type = 'all', incpaths_lst = [], bld_incpaths_lst = [], mlltasks = [], mlytasks = [], mlitasks = [], native_tasks = [], bytecode_tasks = [], linktasks = [], bytecode_env = None, native_env = None, compiled_tasks = [], includes = '', uselib = '', are_deps_set = 0) @feature('ocaml') @after_method('init_ml') def init_envs_ml(self): self.islibrary = getattr(self, 'islibrary', False) global native_lst, bytecode_lst self.native_env = None if self.type in native_lst: self.native_env = self.env.derive() if self.islibrary: self.native_env['OCALINKFLAGS'] = '-a' self.bytecode_env = None if self.type in bytecode_lst: self.bytecode_env = self.env.derive() if self.islibrary: self.bytecode_env['OCALINKFLAGS'] = '-a' if self.type == 'c_object': self.native_env.append_unique('OCALINKFLAGS_OPT', '-output-obj') @feature('ocaml') @before_method('apply_vars_ml') @after_method('init_envs_ml') def apply_incpaths_ml(self): inc_lst = self.includes.split() lst = self.incpaths_lst for dir in inc_lst: node = self.path.find_dir(dir) if not node: error("node not found: " + str(dir)) continue if not node in lst: lst.append(node) self.bld_incpaths_lst.append(node) # now the nodes are added to self.incpaths_lst @feature('ocaml') @before_method('process_source') def apply_vars_ml(self): for i in self.incpaths_lst: if self.bytecode_env: app = self.bytecode_env.append_value app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) if self.native_env: app = self.native_env.append_value app('OCAMLPATH', ['-I', i.bldpath(), '-I', i.srcpath()]) varnames = ['INCLUDES', 'OCAMLFLAGS', 'OCALINKFLAGS', 'OCALINKFLAGS_OPT'] for name in self.uselib.split(): for vname in varnames: cnt = self.env[vname+'_'+name] if cnt: if self.bytecode_env: self.bytecode_env.append_value(vname, cnt) if self.native_env: self.native_env.append_value(vname, cnt) @feature('ocaml') @after_method('process_source') def apply_link_ml(self): if self.bytecode_env: ext = self.islibrary and '.cma' or '.run' linktask = self.create_task('ocalink') linktask.bytecode = 1 linktask.set_outputs(self.path.find_or_declare(self.target + ext)) linktask.env = self.bytecode_env self.linktasks.append(linktask) if self.native_env: if self.type == 'c_object': ext = '.o' elif self.islibrary: ext = '.cmxa' else: ext = '' linktask = self.create_task('ocalinkx') linktask.set_outputs(self.path.find_or_declare(self.target + ext)) linktask.env = self.native_env self.linktasks.append(linktask) # we produce a .o file to be used by gcc self.compiled_tasks.append(linktask) @extension(*EXT_MLL) def mll_hook(self, node): mll_task = self.create_task('ocamllex', node, node.change_ext('.ml')) mll_task.env = self.native_env.derive() self.mlltasks.append(mll_task) self.source.append(mll_task.outputs[0]) @extension(*EXT_MLY) def mly_hook(self, node): mly_task = self.create_task('ocamlyacc', node, [node.change_ext('.ml'), node.change_ext('.mli')]) mly_task.env = self.native_env.derive() self.mlytasks.append(mly_task) self.source.append(mly_task.outputs[0]) task = self.create_task('ocamlcmi', mly_task.outputs[1], mly_task.outputs[1].change_ext('.cmi')) task.env = self.native_env.derive() @extension(*EXT_MLI) def mli_hook(self, node): task = self.create_task('ocamlcmi', node, node.change_ext('.cmi')) task.env = self.native_env.derive() self.mlitasks.append(task) @extension(*EXT_MLC) def mlc_hook(self, node): task = self.create_task('ocamlcc', node, node.change_ext('.o')) task.env = self.native_env.derive() self.compiled_tasks.append(task) @extension(*EXT_ML) def ml_hook(self, node): if self.native_env: task = self.create_task('ocamlx', node, node.change_ext('.cmx')) task.env = self.native_env.derive() task.incpaths = self.bld_incpaths_lst self.native_tasks.append(task) if self.bytecode_env: task = self.create_task('ocaml', node, node.change_ext('.cmo')) task.env = self.bytecode_env.derive() task.bytecode = 1 task.incpaths = self.bld_incpaths_lst self.bytecode_tasks.append(task) def compile_may_start(self): if not getattr(self, 'flag_deps', ''): self.flag_deps = 1 # the evil part is that we can only compute the dependencies after the # source files can be read (this means actually producing the source files) if getattr(self, 'bytecode', ''): alltasks = self.generator.bytecode_tasks else: alltasks = self.generator.native_tasks self.signature() # ensure that files are scanned - unfortunately tree = self.generator.bld env = self.env for node in self.inputs: lst = tree.node_deps[self.uid()] for depnode in lst: for t in alltasks: if t == self: continue if depnode in t.inputs: self.set_run_after(t) # TODO necessary to get the signature right - for now delattr(self, 'cache_sig') self.signature() return Task.Task.runnable_status(self) class ocamlx(Task.Task): """native caml compilation""" color = 'GREEN' run_str = '${OCAMLOPT} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' scan = scan runnable_status = compile_may_start class ocaml(Task.Task): """bytecode caml compilation""" color = 'GREEN' run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLFLAGS} ${OCAMLINCLUDES} -c -o ${TGT} ${SRC}' scan = scan runnable_status = compile_may_start class ocamlcmi(Task.Task): """interface generator (the .i files?)""" color = 'BLUE' run_str = '${OCAMLC} ${OCAMLPATH} ${OCAMLINCLUDES} -o ${TGT} -c ${SRC}' before = ['ocamlcc', 'ocaml', 'ocamlcc'] class ocamlcc(Task.Task): """ocaml to c interfaces""" color = 'GREEN' run_str = 'cd ${TGT[0].bld_dir()} && ${OCAMLOPT} ${OCAMLFLAGS} ${OCAMLPATH} ${OCAMLINCLUDES} -c ${SRC[0].abspath()}' class ocamllex(Task.Task): """lexical generator""" color = 'BLUE' run_str = '${OCAMLLEX} ${SRC} -o ${TGT}' before = ['ocamlcmi', 'ocaml', 'ocamlcc'] class ocamlyacc(Task.Task): """parser generator""" color = 'BLUE' run_str = '${OCAMLYACC} -b ${TGT[0].bld_base(env)} ${SRC}' before = ['ocamlcmi', 'ocaml', 'ocamlcc'] def link_may_start(self): if getattr(self, 'bytecode', 0): alltasks = self.generator.bytecode_tasks else: alltasks = self.generator.native_tasks for x in alltasks: if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'order', ''): # now reorder the inputs given the task dependencies # this part is difficult, we do not have a total order on the tasks # if the dependencies are wrong, this may not stop seen = [] pendant = []+alltasks while pendant: task = pendant.pop(0) if task in seen: continue for x in task.run_after: if not x in seen: pendant.append(task) break else: seen.append(task) self.inputs = [x.outputs[0] for x in seen] self.order = 1 return Task.Task.runnable_status(self) class ocalink(Task.Task): """bytecode caml link""" color = 'YELLOW' run_str = '${OCAMLC} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS} ${SRC}' runnable_status = link_may_start after = ['ocaml', 'ocamlcc'] class ocalinkx(Task.Task): """native caml link""" color = 'YELLOW' run_str = '${OCAMLOPT} -o ${TGT} ${OCAMLINCLUDES} ${OCALINKFLAGS_OPT} ${SRC}' runnable_status = link_may_start after = ['ocamlx', 'ocamlcc'] def configure(conf): opt = conf.find_program('ocamlopt', var='OCAMLOPT', mandatory=False) occ = conf.find_program('ocamlc', var='OCAMLC', mandatory=False) if (not opt) or (not occ): conf.fatal('The objective caml compiler was not found:\ninstall it or make it available in your PATH') v = conf.env v['OCAMLC'] = occ v['OCAMLOPT'] = opt v['OCAMLLEX'] = conf.find_program('ocamllex', var='OCAMLLEX', mandatory=False) v['OCAMLYACC'] = conf.find_program('ocamlyacc', var='OCAMLYACC', mandatory=False) v['OCAMLFLAGS'] = '' v['OCAMLLIB'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIBPATH_OCAML'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['INCLUDES_OCAML'] = conf.cmd_and_log(conf.env['OCAMLC']+' -where').strip()+os.sep v['LIB_OCAML'] = 'camlrun' debian/waf-1.6/waflib/extras/lru_cache.py0000664000000000000000000000457612145744415015343 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy 2011 import os, shutil, re from waflib import Options, Build, Logs """ Apply a least recently used policy to the Waf cache. For performance reasons, it is called after the build is complete. We assume that the the folders are written atomically Do export WAFCACHE=/tmp/foo_xyz where xyz represents the cache size in bytes If missing, the default cache size will be set to 10GB """ re_num = re.compile('[a-zA-Z_-]+(\d+)') CACHESIZE = 10*1024*1024*1024 # in bytes CLEANRATIO = 0.8 DIRSIZE = 4096 def compile(self): if Options.cache_global and not Options.options.nocache: try: os.makedirs(Options.cache_global) except: pass try: self.raw_compile() finally: if Options.cache_global and not Options.options.nocache: self.sweep() def sweep(self): global CACHESIZE CACHEDIR = Options.cache_global # get the cache max size from the WAFCACHE filename re_num = re.compile('[a-zA-Z_]+(\d+)') val = re_num.sub('\\1', os.path.basename(Options.cache_global)) try: CACHESIZE = int(val) except: pass # map folder names to timestamps flist = {} for x in os.listdir(CACHEDIR): j = os.path.join(CACHEDIR, x) if os.path.isdir(j) and len(x) == 64: # dir names are md5 hexdigests flist[x] = [os.stat(j).st_mtime, 0] for (x, v) in flist.items(): cnt = DIRSIZE # each entry takes 4kB d = os.path.join(CACHEDIR, x) for k in os.listdir(d): cnt += os.stat(os.path.join(d, k)).st_size flist[x][1] = cnt total = sum([x[1] for x in flist.values()]) Logs.debug('lru: Cache size is %r' % total) if total >= CACHESIZE: Logs.debug('lru: Trimming the cache since %r > %r' % (total, CACHESIZE)) # make a list to sort the folders by timestamp lst = [(p, v[0], v[1]) for (p, v) in flist.items()] lst.sort(key=lambda x: x[1]) # sort by timestamp lst.reverse() while total >= CACHESIZE * CLEANRATIO: (k, t, s) = lst.pop() p = os.path.join(CACHEDIR, k) v = p + '.del' try: os.rename(p, v) except: # someone already did it pass else: try: shutil.rmtree(v) except: # this should not happen, but who knows? Logs.warn('If you ever see this message, report it (%r)' % v) total -= s del flist[k] Logs.debug('lru: Total at the end %r' % total) Build.BuildContext.raw_compile = Build.BuildContext.compile Build.BuildContext.compile = compile Build.BuildContext.sweep = sweep debian/waf-1.6/waflib/extras/xcode.py0000664000000000000000000002031212145744415014502 0ustar #! /usr/bin/env python # encoding: utf-8 # XCode 3/XCode 4 generator for Waf # Nicolas Mercier 2011 """ Usage: def options(opt): opt.load('xcode') $ waf configure xcode """ # TODO: support iOS projects from waflib import Context, TaskGen, Build, Utils import os, sys, random, time HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)' MAP_EXT = { '.h' : "sourcecode.c.h", '.hh': "sourcecode.cpp.h", '.inl': "sourcecode.cpp.h", '.hpp': "sourcecode.cpp.h", '.c': "sourcecode.c.c", '.m': "sourcecode.c.objc", '.mm': "sourcecode.cpp.objcpp", '.cc': "sourcecode.cpp.cpp", '.cpp': "sourcecode.cpp.cpp", '.C': "sourcecode.cpp.cpp", '.cxx': "sourcecode.cpp.cpp", '.c++': "sourcecode.cpp.cpp", '.l': "sourcecode.lex", # luthor '.ll': "sourcecode.lex", '.y': "sourcecode.yacc", '.yy': "sourcecode.yacc", '.plist': "text.plist.xml", ".nib": "wrapper.nib", ".xib": "text.xib", } part1 = 0 part2 = 10000 part3 = 0 id = 562000999 def newid(): global id id = id + 1 return "%04X%04X%04X%012d" % (0, 10000, 0, id) class XCodeNode: def __init__(self): self._id = newid() def tostring(self, value): if isinstance(value, dict): result = "{\n" for k,v in value.items(): result = result + "\t\t\t%s = %s;\n" % (k, self.tostring(v)) result = result + "\t\t}" return result elif isinstance(value, str): return "\"%s\"" % value elif isinstance(value, list): result = "(\n" for i in value: result = result + "\t\t\t%s,\n" % self.tostring(i) result = result + "\t\t)" return result elif isinstance(value, XCodeNode): return value._id else: return str(value) def write_recursive(self, value, file): if isinstance(value, dict): for k,v in value.items(): self.write_recursive(v, file) elif isinstance(value, list): for i in value: self.write_recursive(i, file) elif isinstance(value, XCodeNode): value.write(file) def write(self, file): for attribute,value in self.__dict__.items(): if attribute[0] != '_': self.write_recursive(value, file) w = file.write w("\t%s = {\n" % self._id) w("\t\tisa = %s;\n" % self.__class__.__name__) for attribute,value in self.__dict__.items(): if attribute[0] != '_': w("\t\t%s = %s;\n" % (attribute, self.tostring(value))) w("\t};\n\n") # Configurations class XCBuildConfiguration(XCodeNode): def __init__(self, name, settings = {}, env=None): XCodeNode.__init__(self) self.baseConfigurationReference = "" self.buildSettings = settings self.name = name if env and env.ARCH: settings['ARCHS'] = " ".join(env.ARCH) class XCConfigurationList(XCodeNode): def __init__(self, settings): XCodeNode.__init__(self) self.buildConfigurations = settings self.defaultConfigurationIsVisible = 0 self.defaultConfigurationName = settings and settings[0].name or "" # Group/Files class PBXFileReference(XCodeNode): def __init__(self, name, path, filetype = '', sourcetree = "SOURCE_ROOT"): XCodeNode.__init__(self) self.fileEncoding = 4 if not filetype: _, ext = os.path.splitext(name) filetype = MAP_EXT.get(ext, 'text') self.lastKnownFileType = filetype self.name = name self.path = path self.sourceTree = sourcetree class PBXGroup(XCodeNode): def __init__(self, name, sourcetree = ""): XCodeNode.__init__(self) self.children = [] self.name = name self.sourceTree = sourcetree def add(self, root, sources): folders = {} def folder(n): if n == root: return self try: return folders[n] except KeyError: f = PBXGroup(n.name) p = folder(n.parent) folders[n] = f p.children.append(f) return f for s in sources: f = folder(s.parent) source = PBXFileReference(s.name, s.abspath()) f.children.append(source) # Targets class PBXLegacyTarget(XCodeNode): def __init__(self, action, target=''): XCodeNode.__init__(self) self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) if not target: self.buildArgumentsString = "%s %s" % (sys.argv[0], action) else: self.buildArgumentsString = "%s %s --targets=%s" % (sys.argv[0], action, target) self.buildPhases = [] self.buildToolPath = sys.executable self.buildWorkingDirectory = "" self.dependencies = [] self.name = target or action self.productName = target or action self.passBuildSettingsInEnvironment = 0 class PBXShellScriptBuildPhase(XCodeNode): def __init__(self, action, target): XCodeNode.__init__(self) self.buildActionMask = 2147483647 self.files = [] self.inputPaths = [] self.outputPaths = [] self.runOnlyForDeploymentPostProcessing = 0 self.shellPath = "/bin/sh" self.shellScript = "%s %s %s --targets=%s" % (sys.executable, sys.argv[0], action, target) class PBXNativeTarget(XCodeNode): def __init__(self, action, target, node, env): XCodeNode.__init__(self) conf = XCBuildConfiguration('waf', {'PRODUCT_NAME':target, 'CONFIGURATION_BUILD_DIR':node.parent.abspath()}, env) self.buildConfigurationList = XCConfigurationList([conf]) self.buildPhases = [PBXShellScriptBuildPhase(action, target)] self.buildRules = [] self.dependencies = [] self.name = target self.productName = target self.productType = "com.apple.product-type.application" self.productReference = PBXFileReference(target, node.abspath(), 'wrapper.application', 'BUILT_PRODUCTS_DIR') # Root project object class PBXProject(XCodeNode): def __init__(self, name, version): XCodeNode.__init__(self) self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) self.compatibilityVersion = version[0] self.hasScannedForEncodings = 1; self.mainGroup = PBXGroup(name) self.projectRoot = "" self.projectDirPath = "" self.targets = [] self._objectVersion = version[1] self._output = PBXGroup('out') self.mainGroup.children.append(self._output) def write(self, file): w = file.write w("// !$*UTF8*$!\n") w("{\n") w("\tarchiveVersion = 1;\n") w("\tclasses = {\n") w("\t};\n") w("\tobjectVersion = %d;\n" % self._objectVersion) w("\tobjects = {\n\n") XCodeNode.write(self, file) w("\t};\n") w("\trootObject = %s;\n" % self._id) w("}\n") def add_task_gen(self, tg): if not getattr(tg, 'mac_app', False): self.targets.append(PBXLegacyTarget('build', tg.name)) else: target = PBXNativeTarget('build', tg.name, tg.link_task.outputs[0].change_ext('.app'), tg.env) self.targets.append(target) self._output.children.append(target.productReference) class xcode(Build.BuildContext): cmd = 'xcode' fun = 'build' def collect_source(self, tg): source_files = tg.to_nodes(getattr(tg, 'source', [])) plist_files = tg.to_nodes(getattr(tg, 'mac_plist', [])) resource_files = [tg.path.find_node(i) for i in Utils.to_list(getattr(tg, 'mac_resources', []))] include_dirs = Utils.to_list(getattr(tg, 'includes', [])) + Utils.to_list(getattr(tg, 'export_dirs', [])) include_files = [] for x in include_dirs: if not isinstance(x, str): include_files.append(x) continue d = tg.path.find_node(x) if d: lst = [y for y in d.ant_glob(HEADERS_GLOB, flat=False)] include_files.extend(lst) # remove duplicates source = list(set(source_files + plist_files + resource_files + include_files)) source.sort(key=lambda x: x.abspath()) return source def execute(self): """ Entry point """ self.restore() if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath())) p = PBXProject(appname, ('Xcode 3.2', 46)) for g in self.groups: for tg in g: if not isinstance(tg, TaskGen.task_gen): continue tg.post() features = Utils.to_list(getattr(tg, 'features', '')) group = PBXGroup(tg.name) group.add(tg.path, self.collect_source(tg)) p.mainGroup.children.append(group) if 'cprogram' or 'cxxprogram' in features: p.add_task_gen(tg) # targets that don't produce the executable but that you might want to run p.targets.append(PBXLegacyTarget('configure')) p.targets.append(PBXLegacyTarget('dist')) p.targets.append(PBXLegacyTarget('install')) p.targets.append(PBXLegacyTarget('check')) node = self.srcnode.make_node('%s.xcodeproj' % appname) node.mkdir() node = node.make_node('project.pbxproj') p.write(open(node.abspath(), 'w')) debian/waf-1.6/waflib/extras/gob2.py0000664000000000000000000000047212145744415014236 0ustar #!/usr/bin/env python # encoding: utf-8 # Ali Sabil, 2007 from waflib import TaskGen TaskGen.declare_chain( name = 'gob2', rule = '${GOB2} -o ${TGT[0].bld_dir()} ${GOB2FLAGS} ${SRC}', ext_in = '.gob', ext_out = '.c' ) def configure(conf): conf.find_program('gob2', var='GOB2') conf.env['GOB2FLAGS'] = '' debian/waf-1.6/waflib/extras/__init__.py0000664000000000000000000000010712145744415015137 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) debian/waf-1.6/waflib/extras/slow_qt4.py0000664000000000000000000000527212145744415015164 0ustar #! /usr/bin/env python # Thomas Nagy, 2011 (ita) """ Create _moc.cpp files The builds are 30-40% faster when .moc files are included, you should NOT use this tool. If you really really want it: def configure(conf): conf.load('compiler_cxx qt4') conf.load('slow_qt4') See playground/slow_qt/wscript for a complete example. """ from waflib.TaskGen import extension from waflib import Task import waflib.Tools.qt4 import waflib.Tools.cxx @extension(*waflib.Tools.qt4.EXT_QT4) def cxx_hook(self, node): self.create_compiled_task('cxx_qt', node) class cxx_qt(waflib.Tools.cxx.cxx): def runnable_status(self): ret = waflib.Tools.cxx.cxx.runnable_status(self) if ret != Task.ASK_LATER and not getattr(self, 'moc_done', None): try: cache = self.generator.moc_cache except AttributeError: cache = self.generator.moc_cache = {} deps = self.generator.bld.node_deps[self.uid()] for x in [self.inputs[0]] + deps: if x.read().find('Q_OBJECT') > 0: # process "foo.h -> foo.moc" only if "foo.cpp" is in the sources for the current task generator # this code will work because it is in the main thread (runnable_status) if x.name.rfind('.') > -1: # a .h file... name = x.name[:x.name.rfind('.')] for tsk in self.generator.compiled_tasks: if tsk.inputs and tsk.inputs[0].name.startswith(name): break else: # no corresponding file, continue continue # the file foo.cpp could be compiled for a static and a shared library - hence the %number in the name cxx_node = x.parent.get_bld().make_node(x.name.replace('.', '_') + '_%d_moc.cpp' % self.generator.idx) if cxx_node in cache: continue cache[cxx_node] = self tsk = Task.classes['moc'](env=self.env, generator=self.generator) tsk.set_inputs(x) tsk.set_outputs(cxx_node) if x.name.endswith('.cpp'): # moc is trying to be too smart but it is too dumb: # why forcing the #include when Q_OBJECT is in the cpp file? gen = self.generator.bld.producer gen.outstanding.insert(0, tsk) gen.total += 1 self.set_run_after(tsk) else: cxxtsk = Task.classes['cxx'](env=self.env, generator=self.generator) cxxtsk.set_inputs(tsk.outputs) cxxtsk.set_outputs(cxx_node.change_ext('.o')) cxxtsk.set_run_after(tsk) try: self.more_tasks.extend([tsk, cxxtsk]) except AttributeError: self.more_tasks = [tsk, cxxtsk] try: link = self.generator.link_task except: pass else: link.set_run_after(cxxtsk) link.inputs.extend(cxxtsk.outputs) self.moc_done = True for t in self.run_after: if not t.hasrun: return Task.ASK_LATER return ret debian/waf-1.6/waflib/extras/dumbpreproc.py0000664000000000000000000000272312145744415015730 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Dumb C/C++ preprocessor for finding dependencies It will look at all include files it can find after removing the comments, so the following will always add the dependency on both "a.h" and "b.h":: #include "a.h" #ifdef B #include "b.h" #endif int main() { return 0; } To use:: def configure(conf): conf.load('compiler_c') conf.load('c_dumbpreproc') """ import re, sys, os, string, traceback from waflib import Logs, Build, Utils, Errors from waflib.Logs import debug, error from waflib.Tools import c_preproc re_inc = re.compile( '^[ \t]*(#|%:)[ \t]*(include)[ \t]*[<"](.*)[>"]\r*$', re.IGNORECASE | re.MULTILINE) def lines_includes(node): code = node.read() if c_preproc.use_trigraphs: for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) return [(m.group(2), m.group(3)) for m in re.finditer(re_inc, code)] parser = c_preproc.c_parser class dumb_parser(parser): def addlines(self, node): if node in self.nodes[:-1]: return self.currentnode_stack.append(node.parent) self.lines = lines_includes(node) + [(c_preproc.POPFILE, '')] + self.lines def start(self, node, env): self.addlines(node) while self.lines: (x, y) = self.lines.pop(0) if x == c_preproc.POPFILE: self.currentnode_stack.pop() continue self.tryfind(y) c_preproc.c_parser = dumb_parser debian/waf-1.6/waflib/extras/md5_tstamp.py0000664000000000000000000000360312145744415015461 0ustar #! /usr/bin/env python # encoding: utf-8 """ Store some values on the buildcontext mapping file paths to stat values and md5 values (timestamp + md5) this way the md5 hashes are computed only when timestamp change (can be faster) There is usually little or no gain from enabling this, but it can be used to enable the second level cache with timestamps (WAFCACHE) You may have to run distclean or to remove the build directory before enabling/disabling this hashing scheme """ import os, stat try: import cPickle except: import pickle as cPickle from waflib import Utils, Build, Context STRONGEST = True Context.DBFILE += '_md5tstamp' Build.hashes_md5_tstamp = {} Build.SAVED_ATTRS.append('hashes_md5_tstamp') def store(self): # save the hash cache as part of the default pickle file self.hashes_md5_tstamp = Build.hashes_md5_tstamp self.store_real() Build.BuildContext.store_real = Build.BuildContext.store Build.BuildContext.store = store def restore(self): # we need a module variable for h_file below self.restore_real() try: Build.hashes_md5_tstamp = self.hashes_md5_tstamp or {} except Exception as e: Build.hashes_md5_tstamp = {} Build.BuildContext.restore_real = Build.BuildContext.restore Build.BuildContext.restore = restore def h_file(filename): st = os.stat(filename) if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('not a file') if filename in Build.hashes_md5_tstamp: if Build.hashes_md5_tstamp[filename][0] == str(st.st_mtime): return Build.hashes_md5_tstamp[filename][1] m = Utils.md5() if STRONGEST: f = open(filename, 'rb') read = 1 try: while read: read = f.read(100000) m.update(read) finally: f.close() else: m.update(str(st.st_mtime)) m.update(str(st.st_size)) m.update(filename) # ensure that the cache is overwritten Build.hashes_md5_tstamp[filename] = (str(st.st_mtime), m.digest()) return m.digest() Utils.h_file = h_file debian/waf-1.6/waflib/extras/review.py0000664000000000000000000002203312145744415014703 0ustar #!/usr/bin/env python # encoding: utf-8 # Laurent Birtz, 2011 # moved the code into a separate tool (ita) """ There are several things here: - a different command-line option management making options persistent - the review command to display the options set Assumptions: - configuration options are not always added to the right group (and do not count on the users to do it...) - the options are persistent between the executions (waf options are NOT persistent by design), even for the configuration - when the options change, the build is invalidated (forcing a reconfiguration) """ import os, textwrap, shutil from waflib import Logs, Context, ConfigSet, Options, Build, Configure class Odict(dict): """Ordered dictionary""" def __init__(self, data=None): self._keys = [] dict.__init__(self) if data: # we were provided a regular dict if isinstance(data, dict): self.append_from_dict(data) # we were provided a tuple list elif type(data) == list: self.append_from_plist(data) # we were provided invalid input else: raise Exception("expected a dict or a tuple list") def append_from_dict(self, dict): map(self.__setitem__, dict.keys(), dict.values()) def append_from_plist(self, plist): for pair in plist: if len(pair) != 2: raise Exception("invalid pairs list") for (k, v) in plist: self.__setitem__(k, v) def __delitem__(self, key): if not key in self._keys: raise KeyError(key) dict.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): dict.__setitem__(self, key, item) if key not in self._keys: self._keys.append(key) def clear(self): dict.clear(self) self._keys = [] def copy(self): return Odict(self.plist()) def items(self): return zip(self._keys, self.values()) def keys(self): return list(self._keys) # return a copy of the list def values(self): return map(self.get, self._keys) def plist(self): p = [] for k, v in self.items(): p.append( (k, v) ) return p def __str__(self): s = "{" l = len(self._keys) for k, v in self.items(): l -= 1 strkey = str(k) if isinstance(k, basestring): strkey = "'"+strkey+"'" strval = str(v) if isinstance(v, basestring): strval = "'"+strval+"'" s += strkey + ":" + strval if l > 0: s += ", " s += "}" return s review_options = Odict() """ Ordered dictionary mapping configuration option names to their optparse option. """ review_defaults = {} """ Dictionary mapping configuration option names to their default value. """ old_review_set = None """ Review set containing the configuration values before parsing the command line. """ new_review_set = None """ Review set containing the configuration values after parsing the command line. """ class OptionsReview(Options.OptionsContext): def __init__(self, **kw): super(self.__class__, self).__init__(**kw) def prepare_config_review(self): """ Find the configuration options that are reviewable, detach their default value from their optparse object and store them into the review dictionaries. """ gr = self.get_option_group('configure options') for opt in gr.option_list: if opt.action != 'store' or opt.dest in ("out", "top"): continue review_options[opt.dest] = opt review_defaults[opt.dest] = opt.default if gr.defaults.has_key(opt.dest): del gr.defaults[opt.dest] opt.default = None def parse_args(self): self.prepare_config_review() self.parser.get_option('--prefix').help = 'installation prefix' super(OptionsReview, self).parse_args() Context.create_context('review').refresh_review_set() class ReviewContext(Context.Context): '''reviews the configuration values''' cmd = 'review' def __init__(self, **kw): super(self.__class__, self).__init__(**kw) out = Options.options.out if not out: out = getattr(Context.g_module, Context.OUT, None) if not out: out = Options.lockfile.replace('.lock-waf', '') self.build_path = (os.path.isabs(out) and self.root or self.path).make_node(out).abspath() """Path to the build directory""" self.cache_path = os.path.join(self.build_path, Build.CACHE_DIR) """Path to the cache directory""" self.review_path = os.path.join(self.cache_path, 'review.cache') """Path to the review cache file""" def execute(self): """ Display and store the review set. Invalidate the cache as required. """ if not self.compare_review_set(old_review_set, new_review_set): self.invalidate_cache() self.store_review_set(new_review_set) print(self.display_review_set(new_review_set)) def invalidate_cache(self): """Invalidate the cache to prevent bad builds.""" try: Logs.warn("Removing the cached configuration since the options have changed") shutil.rmtree(self.cache_path) except: pass def refresh_review_set(self): """ Obtain the old review set and the new review set, and import the new set. """ global old_review_set, new_review_set old_review_set = self.load_review_set() new_review_set = self.update_review_set(old_review_set) self.import_review_set(new_review_set) def load_review_set(self): """ Load and return the review set from the cache if it exists. Otherwise, return an empty set. """ if os.path.isfile(self.review_path): return ConfigSet.ConfigSet(self.review_path) return ConfigSet.ConfigSet() def store_review_set(self, review_set): """ Store the review set specified in the cache. """ if not os.path.isdir(self.cache_path): os.makedirs(self.cache_path) review_set.store(self.review_path) def update_review_set(self, old_set): """ Merge the options passed on the command line with those imported from the previous review set and return the corresponding preview set. """ # Convert value to string. It's important that 'None' maps to # the empty string. def val_to_str(val): if val == None or val == '': return '' return str(val) new_set = ConfigSet.ConfigSet() opt_dict = Options.options.__dict__ for name in review_options.keys(): # the option is specified explicitly on the command line if name in opt_dict: # if the option is the default, pretend it was never specified if val_to_str(opt_dict[name]) != val_to_str(review_defaults[name]): new_set[name] = opt_dict[name] # the option was explicitly specified in a previous command elif name in old_set: new_set[name] = old_set[name] return new_set def import_review_set(self, review_set): """ Import the actual value of the reviewable options in the option dictionary, given the current review set. """ for name in review_options.keys(): if name in review_set: value = review_set[name] else: value = review_defaults[name] setattr(Options.options, name, value) def compare_review_set(self, set1, set2): """ Return true if the review sets specified are equal. """ if len(set1.keys()) != len(set2.keys()): return False for key in set1.keys(): if not key in set2 or set1[key] != set2[key]: return False return True def display_review_set(self, review_set): """ Return the string representing the review set specified. """ term_width = Logs.get_term_cols() lines = [] for dest in review_options.keys(): opt = review_options[dest] name = ", ".join(opt._short_opts + opt._long_opts) help = opt.help actual = None if dest in review_set: actual = review_set[dest] default = review_defaults[dest] lines.append(self.format_option(name, help, actual, default, term_width)) return "Configuration:\n\n" + "\n\n".join(lines) + "\n" def format_option(self, name, help, actual, default, term_width): """ Return the string representing the option specified. """ def val_to_str(val): if val == None or val == '': return "(void)" return str(val) max_name_len = 20 sep_len = 2 w = textwrap.TextWrapper() w.width = term_width - 1 if w.width < 60: w.width = 60 out = "" # format the help out += w.fill(help) + "\n" # format the name name_len = len(name) out += Logs.colors.CYAN + name + Logs.colors.NORMAL # set the indentation used when the value wraps to the next line w.subsequent_indent = " ".rjust(max_name_len + sep_len) w.width -= (max_name_len + sep_len) # the name string is too long, switch to the next line if name_len > max_name_len: out += "\n" + w.subsequent_indent # fill the remaining of the line with spaces else: out += " ".rjust(max_name_len + sep_len - name_len) # format the actual value, if there is one if actual != None: out += Logs.colors.BOLD + w.fill(val_to_str(actual)) + Logs.colors.NORMAL + "\n" + w.subsequent_indent # format the default value default_fmt = val_to_str(default) if actual != None: default_fmt = "default: " + default_fmt out += Logs.colors.NORMAL + w.fill(default_fmt) + Logs.colors.NORMAL return out # Monkey-patch ConfigurationContext.execute() to have it store the review set. old_configure_execute = Configure.ConfigurationContext.execute def new_configure_execute(self): old_configure_execute(self) Context.create_context('review').store_review_set(new_review_set) Configure.ConfigurationContext.execute = new_configure_execute debian/waf-1.6/waflib/extras/biber.py0000664000000000000000000000314312145744415014466 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2011 (ita) """ Latex processing using "biber" """ import os from waflib import Task from waflib.Logs import warn from waflib.Tools import tex as texmodule class tex(texmodule.tex): biber_fun, _ = Task.compile_fun('${BIBER} ${BIBERFLAGS} ${SRCFILE}',shell=False) biber_fun.__doc__ = """ Execute the program **biber** """ def bibfile(self): return None def bibunits(self): self.env.env = {} self.env.env.update(os.environ) self.env.env.update({'BIBINPUTS': self.TEXINPUTS, 'BSTINPUTS': self.TEXINPUTS}) self.env.SRCFILE = self.aux_node.name[:-4] if not self.env['PROMPT_LATEX']: self.env.append_unique('BIBERFLAGS', '--quiet') path = self.aux_node.abspath()[:-4] + '.bcf' if os.path.isfile(path): warn('calling biber') self.check_status('error when calling biber, check %s.blg for errors' % (self.env.SRCFILE), self.biber_fun()) else: super(tex, self).bibfile() super(tex, self).bibunits() class latex(tex): texfun, vars = Task.compile_fun('${LATEX} ${LATEXFLAGS} ${SRCFILE}', shell=False) class pdflatex(tex): texfun, vars = Task.compile_fun('${PDFLATEX} ${PDFLATEXFLAGS} ${SRCFILE}', shell=False) class xelatex(tex): texfun, vars = Task.compile_fun('${XELATEX} ${XELATEXFLAGS} ${SRCFILE}', shell=False) def configure(self): """ Almost the same as in tex.py, but try to detect 'biber' """ v = self.env for p in ' biber tex latex pdflatex xelatex bibtex dvips dvipdf ps2pdf makeindex pdf2ps'.split(): try: self.find_program(p, var=p.upper()) except self.errors.ConfigurationError: pass v['DVIPSFLAGS'] = '-Ppdf' debian/waf-1.6/waflib/extras/softlink_libs.py0000664000000000000000000000451112145744415016245 0ustar #! /usr/bin/env python # per rosengren 2011 from waflib.TaskGen import feature, after_method from waflib.Task import Task, always_run from os.path import basename, isabs from os import tmpfile, linesep def options(opt): grp = opt.add_option_group('Softlink Libraries Options') grp.add_option('--exclude', default='/usr/lib,/lib', help='No symbolic links are created for libs within [%default]') def configure(cnf): cnf.find_program('ldd') if not cnf.env.SOFTLINK_EXCLUDE: cnf.env.SOFTLINK_EXCLUDE = cnf.options.exclude.split(',') @feature('softlink_libs') @after_method('process_rule') def add_finder(self): tgt = self.path.find_or_declare(self.target) self.create_task('sll_finder', tgt=tgt) self.create_task('sll_installer', tgt=tgt) always_run(sll_installer) class sll_finder(Task): ext_out = 'softlink_libs' def run(self): bld = self.generator.bld linked=[] target_paths = [] for g in bld.groups: for tgen in g: # FIXME it might be better to check if there is a link_task (getattr?) target_paths += [tgen.path.get_bld().bldpath()] linked += [t.outputs[0].bldpath() for t in getattr(tgen, 'tasks', []) if t.__class__.__name__ in ['cprogram', 'cshlib', 'cxxprogram', 'cxxshlib']] lib_list = [] if len(linked): cmd = [self.env.LDD] + linked # FIXME add DYLD_LIBRARY_PATH+PATH for osx+win32 ldd_env = {'LD_LIBRARY_PATH': ':'.join(target_paths + self.env.LIBPATH)} # FIXME the with syntax will not work in python 2 with tmpfile() as result: self.exec_command(cmd, env=ldd_env, stdout=result) result.seek(0) for line in result.readlines(): words = line.split() if len(words) < 3 or words[1] != '=>': continue lib = words[2] if lib == 'not': continue if any([lib.startswith(p) for p in [bld.bldnode.abspath(), '('] + self.env.SOFTLINK_EXCLUDE]): continue if not isabs(lib): continue lib_list.append(lib) lib_list = sorted(set(lib_list)) self.outputs[0].write(linesep.join(lib_list + self.env.DYNAMIC_LIBS)) return 0 class sll_installer(Task): ext_in = 'softlink_libs' def run(self): tgt = self.outputs[0] self.generator.bld.install_files('${LIBDIR}', tgt, postpone=False) lib_list=tgt.read().split() for lib in lib_list: self.generator.bld.symlink_as('${LIBDIR}/'+basename(lib), lib, postpone=False) return 0 debian/waf-1.6/waflib/extras/cython.py0000664000000000000000000000642212145744415014712 0ustar #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 import re import waflib import waflib.Logs as _msg from waflib import Task from waflib.TaskGen import extension, feature, before_method, after_method cy_api_pat = re.compile(r'\s*?cdef\s*?(public|api)\w*') re_cyt = re.compile('import\\s(\\w+)\\s*$', re.M) @extension('.pyx') def add_cython_file(self, node): """ Process a *.pyx* file given in the list of source files. No additional feature is required:: def build(bld): bld(features='c cshlib pyext', source='main.c foo.pyx', target='app') """ ext = '.c' if 'cxx' in self.features: self.env.append_unique('CYTHONFLAGS', '--cplus') ext = '.cc' tsk = self.create_task('cython', node, node.change_ext(ext)) self.source += tsk.outputs class cython(Task.Task): run_str = '${CYTHON} ${CYTHONFLAGS} -o ${TGT[0].abspath()} ${SRC}' color = 'GREEN' vars = ['INCLUDES'] """ Rebuild whenever the INCLUDES change. The variables such as CYTHONFLAGS will be appended by the metaclass. """ ext_out = ['.h'] """ The creation of a .h file is known only after the build has begun, so it is not possible to compute a build order just by looking at the task inputs/outputs. """ def runnable_status(self): """ Perform a double-check to add the headers created by cython to the output nodes. The scanner is executed only when the cython task must be executed (optimization). """ ret = super(cython, self).runnable_status() if ret == Task.ASK_LATER: return ret for x in self.generator.bld.raw_deps[self.uid()]: if x.startswith('header:'): self.outputs.append(self.inputs[0].parent.find_or_declare(x.replace('header:', ''))) return super(cython, self).runnable_status() def scan(self): """ Return the dependent files (.pxd) by looking in the include folders. Put the headers to generate in the custom list "bld.raw_deps". To inspect the scanne results use:: $ waf clean build --zones=deps """ txt = self.inputs[0].read() mods = [] for m in re_cyt.finditer(txt): mods.append(m.group(1)) _msg.debug("cython: mods %r" % mods) incs = getattr(self.generator, 'cython_includes', []) incs = [self.generator.path.find_dir(x) for x in incs] incs.append(self.inputs[0].parent) found = [] missing = [] for x in mods: for y in incs: k = y.find_resource(x + '.pxd') if k: found.append(k) break else: missing.append(x) _msg.debug("cython: found %r" % found) # Now the .h created - store them in bld.raw_deps for later use has_api = False has_public = False for l in txt.splitlines(): if cy_api_pat.match(l): if ' api ' in l: has_api = True if ' public ' in l: has_public = True name = self.inputs[0].name.replace('.pyx', '') if has_api: missing.append('header:%s_api.h' % name) if has_public: missing.append('header:%s.h' % name) return (found, missing) def options(ctx): ctx.add_option('--cython-flags', action='store', default='', help='space separated list of flags to pass to cython') def configure(ctx): if not ctx.env.CC and not ctx.env.CXX: ctx.fatal('Load a C/C++ compiler first') if not ctx.env.PYTHON: ctx.fatal('Load the python tool first!') ctx.find_program('cython', var='CYTHON') if ctx.options.cython_flags: ctx.env.CYTHONFLAGS = ctx.options.cython_flags debian/waf-1.6/waflib/extras/gccdeps.py0000664000000000000000000000535012145744415015015 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2008-2010 (ita) """ Execute the tasks with gcc -MD, read the dependencies from the .d file and prepare the dependency calculation for the next run """ import os, re, threading from waflib import Task, Logs, Utils, Errors from waflib.Tools import c_preproc from waflib.TaskGen import before_method, after_method, feature lock = threading.Lock() preprocessor_flag = '-MD' @feature('cc') @before_method('apply_core') def add_mmd_cc(self): if self.env.get_flat('CFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CFLAGS', [preprocessor_flag]) @feature('cxx') @before_method('apply_core') def add_mmd_cxx(self): if self.env.get_flat('CXXFLAGS').find(preprocessor_flag) < 0: self.env.append_value('CXXFLAGS', [preprocessor_flag]) def scan(self): "the scanner does not do anything initially" nodes = self.generator.bld.node_deps.get(self.uid(), []) names = [] return (nodes, names) re_o = re.compile("\.o$") def post_run(self): # The following code is executed by threads, it is not safe, so a lock is needed... if getattr(self, 'cached', None): return Task.Task.post_run(self) name = self.outputs[0].abspath() name = re_o.sub('.d', name) txt = Utils.readf(name) #os.unlink(name) txt = txt.replace('\\\n', '') lst = txt.strip().split(':') val = ":".join(lst[1:]) val = val.split() nodes = [] bld = self.generator.bld f = re.compile("^(\.\.)[\\/](.*)$") for x in val: node = None if os.path.isabs(x): if not c_preproc.go_absolute: continue lock.acquire() try: node = bld.root.find_resource(x) finally: lock.release() else: path = bld.bldnode x = [k for k in Utils.split_path(x) if k and k != '.'] while lst and x[0] == '..': x = x[1:] path = path.parent # when calling find_resource, make sure the path does not begin by '..' try: lock.acquire() node = path.find_resource(x) finally: lock.release() if not node: raise ValueError('could not find %r for %r' % (x, self)) else: if id(node) == id(self.inputs[0]): # ignore the source file, it is already in the dependencies # this way, successful config tests may be retrieved from the cache continue nodes.append(node) Logs.debug('deps: real scanner for %s returned %s' % (str(self), str(nodes))) bld.node_deps[self.uid()] = nodes bld.raw_deps[self.uid()] = [] try: del self.cache_sig except: pass Task.Task.post_run(self) def sig_implicit_deps(self): try: return Task.Task.sig_implicit_deps(self) except Errors.WafError: return Utils.SIG_NIL for name in 'cc cxx'.split(): try: cls = Task.classes[name] except KeyError: pass else: cls.post_run = post_run cls.scan = scan cls.sig_implicit_deps = sig_implicit_deps debian/waf-1.6/waflib/extras/scala.py0000664000000000000000000000661712145744415014477 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2010 (ita) """ Scala support scalac outputs files a bit where it wants to """ import os, re from waflib.Configure import conf from waflib import TaskGen, Task, Utils, Options, Build, Errors, Node from waflib.TaskGen import feature, before_method, after_method from waflib.Tools import ccroot ccroot.USELIB_VARS['scalac'] = set(['CLASSPATH', 'SCALACFLAGS']) from waflib.Tools import javaw @feature('scalac') @before_method('process_source') def apply_scalac(self): Utils.def_attrs(self, jarname='', classpath='', sourcepath='.', srcdir='.', jar_mf_attributes={}, jar_mf_classpath=[]) nodes_lst = [] outdir = getattr(self, 'outdir', None) if outdir: if not isinstance(outdir, Node.Node): outdir = self.path.get_bld().make_node(self.outdir) else: outdir = self.path.get_bld() outdir.mkdir() self.env['OUTDIR'] = outdir.abspath() self.scalac_task = tsk = self.create_task('scalac') tmp = [] srcdir = getattr(self, 'srcdir', '') if isinstance(srcdir, Node.Node): srcdir = [srcdir] for x in Utils.to_list(srcdir): if isinstance(x, Node.Node): y = x else: y = self.path.find_dir(x) if not y: self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) tmp.append(y) tsk.srcdir = tmp # reuse some code feature('scalac')(javaw.use_javac_files) after_method('apply_scalac')(javaw.use_javac_files) feature('scalac')(javaw.set_classpath) after_method('apply_scalac', 'use_scalac_files')(javaw.set_classpath) SOURCE_RE = '**/*.scala' class scalac(javaw.javac): color = 'GREEN' vars = ['CLASSPATH', 'SCALACFLAGS', 'SCALAC', 'OUTDIR'] def runnable_status(self): """ Wait for dependent tasks to be complete, then read the file system to find the input nodes. """ for t in self.run_after: if not t.hasrun: return Task.ASK_LATER if not self.inputs: global SOURCE_RE self.inputs = [] for x in self.srcdir: self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) return super(javaw.javac, self).runnable_status() def run(self): """ Execute the scalac compiler """ env = self.env gen = self.generator bld = gen.bld wd = bld.bldnode.abspath() def to_list(xx): if isinstance(xx, str): return [xx] return xx self.last_cmd = lst = [] lst.extend(to_list(env['SCALAC'])) lst.extend(['-classpath']) lst.extend(to_list(env['CLASSPATH'])) lst.extend(['-d']) lst.extend(to_list(env['OUTDIR'])) lst.extend(to_list(env['SCALACFLAGS'])) lst.extend([a.abspath() for a in self.inputs]) lst = [x for x in lst if x] try: self.out = self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, output=0, quiet=0)[1] except: self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None) def configure(self): """ Detect the scalac program """ # If SCALA_HOME is set, we prepend it to the path list java_path = self.environ['PATH'].split(os.pathsep) v = self.env if 'SCALA_HOME' in self.environ: java_path = [os.path.join(self.environ['SCALA_HOME'], 'bin')] + java_path self.env['SCALA_HOME'] = [self.environ['SCALA_HOME']] for x in 'scalac scala'.split(): self.find_program(x, var=x.upper(), path_list=java_path) self.env[x.upper()] = self.cmd_to_list(self.env[x.upper()]) if 'CLASSPATH' in self.environ: v['CLASSPATH'] = self.environ['CLASSPATH'] v.SCALACFLAGS = ['-verbose'] if not v['SCALAC']: self.fatal('scalac is required for compiling scala classes') debian/waf-1.6/waflib/extras/print_commands.py0000664000000000000000000000205012145744415016414 0ustar #! /usr/bin/env python """ Illustrate how to override a class method to do something In this case, print the commands being executed as strings (the commands are usually lists, so this can be misleading) """ import sys from waflib import Context, Utils, Logs def exec_command(self, cmd, **kw): subprocess = Utils.subprocess kw['shell'] = isinstance(cmd, str) txt = cmd if isinstance(cmd, list): txt = ' '.join(cmd) print(txt) Logs.debug('runner_env: kw=%s' % kw) try: if self.logger: # warning: may deadlock with a lot of output (subprocess limitation) self.logger.info(cmd) kw['stdout'] = kw['stderr'] = subprocess.PIPE p = subprocess.Popen(cmd, **kw) (out, err) = p.communicate() if out: self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) if err: self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) return p.returncode else: p = subprocess.Popen(cmd, **kw) return p.wait() except OSError: return -1 Context.Context.exec_command = exec_command debian/waf-1.6/waflib/extras/doxygen.py0000664000000000000000000001074712145744415015070 0ustar #! /usr/bin/env python # encoding: UTF-8 # Thomas Nagy 2008-2010 (ita) """ Doxygen support Variables passed to bld(): * doxyfile -- the Doxyfile to use ported from waf 1.5 (incomplete) """ from fnmatch import fnmatchcase import os, os.path, re, stat from waflib import Task, Utils, Node, Logs from waflib.TaskGen import feature DOXY_STR = '${DOXYGEN} - ' DOXY_FMTS = 'html latex man rft xml'.split() DOXY_FILE_PATTERNS = '*.' + ' *.'.join(''' c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx hpp h++ idl odl cs php php3 inc m mm py f90c cc cxx cpp c++ java ii ixx ipp i++ inl h hh hxx '''.split()) re_nl = re.compile('\\\\\r*\n', re.MULTILINE) class doxygen(Task.Task): vars = ['DOXYGEN', 'DOXYFLAGS'] color = 'BLUE' def runnable_status(self): ''' self.pars are populated in runnable_status - because this function is being run *before* both self.pars "consumers" - scan() and run() set output_dir (node) for the output ''' for x in self.run_after: if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'pars', None): txt = self.inputs[0].read() txt = re_nl.sub('', txt) self.pars = Utils.str_to_dict(txt) if not self.pars.get('OUTPUT_DIRECTORY'): self.pars['OUTPUT_DIRECTORY'] = self.inputs[0].parent.get_bld().abspath() if not self.pars.get('INPUT'): self.pars['INPUT'] = self.inputs[0].parent.abspath() if not getattr(self, 'output_dir', None): self.output_dir = self.generator.bld.root.find_dir(self.pars['OUTPUT_DIRECTORY']) self.signature() return Task.Task.runnable_status(self) def scan(self): if self.pars.get('RECURSIVE') == 'YES': Logs.warn("Doxygen RECURSIVE dependencies are not supported") inputs = self.pars.get('INPUT').split() exclude_patterns = self.pars.get('EXCLUDE_PATTERNS', '').split() file_patterns = self.pars.get('FILE_PATTERNS', '').split() if not file_patterns: file_patterns = DOXY_FILE_PATTERNS nodes = [] names = [] for i in inputs: node = self.generator.bld.root.make_node(i) if node: if os.path.isdir(node.abspath()): for m in node.ant_glob(file_patterns): nodes.append(self.generator.bld.root.make_node(m.abspath())) else: nodes.append(node) else: names.append(i) return (nodes, names) def run(self): code = '\n'.join(['%s = %s' % (x, self.pars[x]) for x in self.pars]) code = code.encode() # for python 3 #fmt = DOXY_STR % (self.inputs[0].parent.abspath()) cmd = Utils.subst_vars(DOXY_STR, self.env) env = self.env.env or None proc = Utils.subprocess.Popen(cmd, shell=True, stdin=Utils.subprocess.PIPE, env=env) proc.communicate(code) return proc.returncode def post_run(self): nodes = self.output_dir.ant_glob('**/*') for x in nodes: x.sig = Utils.h_file(x.abspath()) self.outputs += nodes return Task.Task.post_run(self) #def install(self): # if getattr(self.generator, 'install_to', None): # update_build_dir(self.inputs[0].parent, self.env) # pattern = getattr(self, 'instype', 'html/*') # self.generator.bld.install_files(self.generator.install_to, self.generator.path.ant_glob(pattern, dir=0, src=0)) class tar(Task.Task): "quick tar creation" run_str = '${TAR} ${TAROPTS} ${TGT} ${SRC}' color = 'RED' after = ['doxygen'] def runnable_status(self): for x in getattr(self, 'input_tasks', []): if not x.hasrun: return Task.ASK_LATER if not getattr(self, 'tar_done_adding', None): # execute this only once self.tar_done_adding = True for x in getattr(self, 'input_tasks', []): self.set_inputs(x.outputs) if not self.inputs: return Task.SKIP_ME return Task.Task.runnable_status(self) def __str__(self): tgt_str = ' '.join([a.nice_path(self.env) for a in self.outputs]) return '%s: %s\n' % (self.__class__.__name__, tgt_str) @feature('doxygen') def process_doxy(self): if not getattr(self, 'doxyfile', None): self.generator.bld.fatal('no doxyfile??') node = self.doxyfile if not isinstance(node, Node.Node): node = self.path.find_resource(node) if not node: raise ValueError('doxygen file not found') # the task instance dsk = self.create_task('doxygen', node) if getattr(self, 'doxy_tar', None): tsk = self.create_task('tar') tsk.input_tasks = [dsk] tsk.set_outputs(self.path.find_or_declare(self.doxy_tar)) if self.doxy_tar.endswith('bz2'): tsk.env['TAROPTS'] = ['cjf'] elif self.doxy_tar.endswith('gz'): tsk.env['TAROPTS'] = ['czf'] else: tsk.env['TAROPTS'] = ['cf'] def configure(conf): conf.find_program('doxygen', var='DOXYGEN') conf.find_program('tar', var='TAR') debian/waf-1.6/waflib/extras/c_bgxlc.py0000664000000000000000000000130312145744415015000 0ustar #! /usr/bin/env python # encoding: utf-8 # harald at klimachs.de import os from waflib.Tools import ccroot,ar from waflib.Configure import conf from waflib.Tools import xlc # method xlc_common_flags from waflib.Tools.compiler_c import c_compiler c_compiler['linux'].insert(0, 'c_bgxlc') @conf def find_bgxlc(conf): cc = conf.find_program(['bgxlc_r','bgxlc'], var='CC') cc = conf.cmd_to_list(cc) conf.get_xlc_version(cc) conf.env.CC = cc conf.env.CC_NAME = 'bgxlc' def configure(conf): conf.find_bgxlc() conf.find_ar() conf.xlc_common_flags() conf.env.LINKFLAGS_cshlib = ['-G','-Wl,-bexpfull'] conf.env.LINKFLAGS_cprogram = [] conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/extras/pgicc.py0000664000000000000000000000326312145744415014473 0ustar #!/usr/bin/env python # encoding: utf-8 # Antoine Dechaume 2011 """ Detect the PGI C compiler """ import sys, re from waflib.Configure import conf from waflib.Tools.compiler_c import c_compiler c_compiler['linux'].append('pgicc') @conf def find_pgi_compiler(conf, var, name): """ Find the program name, and execute it to ensure it really is itself. """ if sys.platform == 'cygwin': conf.fatal('The PGI compiler does not work on Cygwin') v = conf.env cc = None if v[var]: cc = v[var] elif var in conf.environ: cc = conf.environ[var] if not cc: cc = conf.find_program(name, var=var) if not cc: conf.fatal('PGI Compiler (%s) was not found' % name) cc = conf.cmd_to_list(cc) v[var + '_VERSION'] = conf.get_pgi_version(cc) v[var] = cc v[var + '_NAME'] = 'pgi' @conf def get_pgi_version(conf, cc): """Find the version of a pgi compiler.""" version_re = re.compile(r"The Portland Group", re.I).search cmd = cc + ['-V', '-E'] # Issue 1078, prevent wrappers from linking try: out, err = conf.cmd_and_log(cmd, output=0) except Exception: conf.fatal('Could not find pgi compiler %r' % cmd) if out: match = version_re(out) else: match = version_re(err) if not match: conf.fatal('Could not verify PGI signature') cmd = cc + ['-help=variable'] try: out, err = conf.cmd_and_log(cmd, output=0) except Exception: conf.fatal('Could not find pgi compiler %r' % cmd) version = re.findall('^COMPVER\s*=(.*)', out, re.M) if len(version) != 1: conf.fatal('Could not determine the compiler version') return version[0] def configure(conf): conf.find_pgi_compiler('CC', 'pgcc') conf.find_ar() conf.gcc_common_flags() conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() debian/waf-1.6/waflib/extras/boo.py0000664000000000000000000000431412145744415014163 0ustar #! /usr/bin/env python # encoding: utf-8 # Yannick LM 2011 """ Support for the boo programming language, for example:: bld(features = "boo", # necessary feature source = "src.boo", # list of boo files gen = "world.dll", # target type = "library", # library/exe ("-target:xyz" flag) name = "world" # necessary if the target is referenced by 'use' ) """ from waflib import Task from waflib.Configure import conf from waflib.TaskGen import feature, after, before, extension @extension('.boo') def boo_hook(self, node): # Nothing here yet ... # TODO filter the non-boo source files in 'apply_booc' and remove this method pass @feature('boo') @before('process_source') def apply_booc(self): """Create a booc task """ src_nodes = self.to_nodes(self.source) out_node = self.path.find_or_declare(self.gen) self.boo_task = self.create_task('booc', src_nodes, [out_node]) # Set variables used by the 'booc' task self.boo_task.env.OUT = '-o:%s' % out_node.abspath() # type is "exe" by default type = getattr(self, "type", "exe") self.boo_task.env.BOO_TARGET_TYPE = "-target:%s" % type @feature('boo') @after('apply_boo') def use_boo(self): """" boo applications honor the **use** keyword:: """ dep_names = self.to_list(getattr(self, 'use', [])) for dep_name in dep_names: dep_task_gen = self.bld.get_tgen_by_name(dep_name) if not dep_task_gen: continue dep_task_gen.post() dep_task = getattr(dep_task_gen, 'boo_task', None) if not dep_task: # Try a cs task: dep_task = getattr(dep_task_gen, 'cs_task', None) if not dep_task: # Try a link task: dep_task = getattr(dep_task, 'link_task', None) if not dep_task: # Abort ... continue self.boo_task.set_run_after(dep_task) # order self.boo_task.dep_nodes.extend(dep_task.outputs) # dependency self.boo_task.env.append_value('BOO_FLAGS', '-reference:%s' % dep_task.outputs[0].abspath()) class booc(Task.Task): """Compiles .boo files """ color = 'YELLOW' run_str = '${BOOC} ${BOO_FLAGS} ${BOO_TARGET_TYPE} ${OUT} ${SRC}' @conf def check_booc(self): self.find_program('booc', 'BOOC') self.env.BOO_FLAGS = ['-nologo'] def configure(self): """Check that booc is available """ self.check_booc() debian/waf-1.6/waflib/extras/sas.py0000664000000000000000000000400012145744415014162 0ustar #!/usr/bin/env python # encoding: utf-8 # Mark Coggeshall, 2010 "SAS support" import os, re from waflib import Utils, Task, TaskGen, Runner, Build, Errors, Node from waflib.TaskGen import feature, before_method from waflib.Logs import error, warn, debug sas_fun, _ = Task.compile_fun('sas -sysin ${SRCFILE} -log ${LOGFILE} -print ${LSTFILE}', shell=False) class sas(Task.Task): vars = ['SAS', 'SASFLAGS'] def run(task): command = 'SAS' env = task.env bld = task.generator.bld fun = sas_fun node = task.inputs[0] logfilenode = node.change_ext('.log') lstfilenode = node.change_ext('.lst') # set the cwd task.cwd = task.inputs[0].parent.get_src().abspath() debug('runner: %s on %s' % (command, node.abspath)) SASINPUTS = node.parent.get_bld().abspath() + os.pathsep + node.parent.get_src().abspath() + os.pathsep task.env.env = {'SASINPUTS': SASINPUTS} task.env.SRCFILE = node.abspath() task.env.LOGFILE = logfilenode.abspath() task.env.LSTFILE = lstfilenode.abspath() ret = fun(task) if ret: error('Running %s on %r returned a non-zero exit' % (command, node)) error('SRCFILE = %r' % node) error('LOGFILE = %r' % logfilenode) error('LSTFILE = %r' % lstfilenode) return ret @feature('sas') @before_method('process_source') def apply_sas(self): if not getattr(self, 'type', None) in ['sas']: self.type = 'sas' self.env['logdir'] = getattr(self, 'logdir', 'log') self.env['lstdir'] = getattr(self, 'lstdir', 'lst') deps_lst = [] if getattr(self, 'deps', None): deps = self.to_list(self.deps) for filename in deps: n = self.path.find_resource(filename) if not n: n = self.bld.root.find_resource(filename) if not n: raise Errors.WafError('cannot find input file %s for processing' % filename) if not n in deps_lst: deps_lst.append(n) for node in self.to_nodes(self.source): if self.type == 'sas': task = self.create_task('sas', src=node) task.dep_nodes = deps_lst self.source = [] def configure(self): self.find_program('sas', var='SAS', mandatory=False) debian/waf-1.6/waflib/extras/misc.py0000664000000000000000000002673512145744415014352 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ This tool is totally deprecated Try using: .pc.in files for .pc files the feature intltool_in - see demos/intltool make-like rules """ import shutil, re, os from waflib import TaskGen, Node, Task, Utils, Build, Errors from waflib.TaskGen import feature, after_method, before_method from waflib.Logs import debug def copy_attrs(orig, dest, names, only_if_set=False): """ copy class attributes from an object to another """ for a in Utils.to_list(names): u = getattr(orig, a, ()) if u or not only_if_set: setattr(dest, a, u) def copy_func(tsk): "Make a file copy. This might be used to make other kinds of file processing (even calling a compiler is possible)" env = tsk.env infile = tsk.inputs[0].abspath() outfile = tsk.outputs[0].abspath() try: shutil.copy2(infile, outfile) except (OSError, IOError): return 1 else: if tsk.chmod: os.chmod(outfile, tsk.chmod) return 0 def action_process_file_func(tsk): "Ask the function attached to the task to process it" if not tsk.fun: raise Errors.WafError('task must have a function attached to it for copy_func to work!') return tsk.fun(tsk) @feature('cmd') def apply_cmd(self): "call a command everytime" if not self.fun: raise Errors.WafError('cmdobj needs a function!') tsk = Task.TaskBase() tsk.fun = self.fun tsk.env = self.env self.tasks.append(tsk) tsk.install_path = self.install_path @feature('copy') @before_method('process_source') def apply_copy(self): Utils.def_attrs(self, fun=copy_func) self.default_install_path = 0 lst = self.to_list(self.source) self.meths.remove('process_source') for filename in lst: node = self.path.find_resource(filename) if not node: raise Errors.WafError('cannot find input file %s for processing' % filename) target = self.target if not target or len(lst)>1: target = node.name # TODO the file path may be incorrect newnode = self.path.find_or_declare(target) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.chmod = getattr(self, 'chmod', Utils.O644) if not tsk.env: tsk.debug() raise Errors.WafError('task without an environment') def subst_func(tsk): "Substitutes variables in a .in file" m4_re = re.compile('@(\w+)@', re.M) code = tsk.inputs[0].read() #Utils.readf(infile) # replace all % by %% to prevent errors by % signs in the input file while string formatting code = code.replace('%', '%%') s = m4_re.sub(r'%(\1)s', code) env = tsk.env di = getattr(tsk, 'dict', {}) or getattr(tsk.generator, 'dict', {}) if not di: names = m4_re.findall(code) for i in names: di[i] = env.get_flat(i) or env.get_flat(i.upper()) tsk.outputs[0].write(s % di) @feature('subst') @before_method('process_source') def apply_subst(self): Utils.def_attrs(self, fun=subst_func) lst = self.to_list(self.source) self.meths.remove('process_source') self.dict = getattr(self, 'dict', {}) for filename in lst: node = self.path.find_resource(filename) if not node: raise Errors.WafError('cannot find input file %s for processing' % filename) if self.target: newnode = self.path.find_or_declare(self.target) else: newnode = node.change_ext('') try: self.dict = self.dict.get_merged_dict() except AttributeError: pass if self.dict and not self.env['DICT_HASH']: self.env = self.env.derive() keys = list(self.dict.keys()) keys.sort() lst = [self.dict[x] for x in keys] self.env['DICT_HASH'] = str(Utils.h_list(lst)) tsk = self.create_task('copy', node, newnode) tsk.fun = self.fun tsk.dict = self.dict tsk.dep_vars = ['DICT_HASH'] tsk.chmod = getattr(self, 'chmod', Utils.O644) if not tsk.env: tsk.debug() raise Errors.WafError('task without an environment') #################### ## command-output #### #################### class cmd_arg(object): """command-output arguments for representing files or folders""" def __init__(self, name, template='%s'): self.name = name self.template = template self.node = None class input_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_resource(self.name) if self.node is None: raise Errors.WafError("Input file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath() else: return self.template % self.node.srcpath() class output_file(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_or_declare(self.name) if self.node is None: raise Errors.WafError("Output file %s not found in " % (self.name, base_path)) def get_path(self, env, absolute): if absolute: return self.template % self.node.abspath() else: return self.template % self.node.bldpath() class cmd_dir_arg(cmd_arg): def find_node(self, base_path): assert isinstance(base_path, Node.Node) self.node = base_path.find_dir(self.name) if self.node is None: raise Errors.WafError("Directory %s not found in " % (self.name, base_path)) class input_dir(cmd_dir_arg): def get_path(self, dummy_env, dummy_absolute): return self.template % self.node.abspath() class output_dir(cmd_dir_arg): def get_path(self, env, dummy_absolute): return self.template % self.node.abspath() class command_output(Task.Task): color = "BLUE" def __init__(self, env, command, command_node, command_args, stdin, stdout, cwd, os_env, stderr): Task.Task.__init__(self, env=env) assert isinstance(command, (str, Node.Node)) self.command = command self.command_args = command_args self.stdin = stdin self.stdout = stdout self.cwd = cwd self.os_env = os_env self.stderr = stderr if command_node is not None: self.dep_nodes = [command_node] self.dep_vars = [] # additional environment variables to look def run(self): task = self #assert len(task.inputs) > 0 def input_path(node, template): if task.cwd is None: return template % node.bldpath() else: return template % node.abspath() def output_path(node, template): fun = node.abspath if task.cwd is None: fun = node.bldpath return template % fun() if isinstance(task.command, Node.Node): argv = [input_path(task.command, '%s')] else: argv = [task.command] for arg in task.command_args: if isinstance(arg, str): argv.append(arg) else: assert isinstance(arg, cmd_arg) argv.append(arg.get_path(task.env, (task.cwd is not None))) if task.stdin: stdin = open(input_path(task.stdin, '%s')) else: stdin = None if task.stdout: stdout = open(output_path(task.stdout, '%s'), "w") else: stdout = None if task.stderr: stderr = open(output_path(task.stderr, '%s'), "w") else: stderr = None if task.cwd is None: cwd = ('None (actually %r)' % os.getcwd()) else: cwd = repr(task.cwd) debug("command-output: cwd=%s, stdin=%r, stdout=%r, argv=%r" % (cwd, stdin, stdout, argv)) if task.os_env is None: os_env = os.environ else: os_env = task.os_env command = Utils.subprocess.Popen(argv, stdin=stdin, stdout=stdout, stderr=stderr, cwd=task.cwd, env=os_env) return command.wait() @feature('command-output') def init_cmd_output(self): Utils.def_attrs(self, stdin = None, stdout = None, stderr = None, # the command to execute command = None, # whether it is an external command; otherwise it is assumed # to be an executable binary or script that lives in the # source or build tree. command_is_external = False, # extra parameters (argv) to pass to the command (excluding # the command itself) argv = [], # dependencies to other objects -> this is probably not what you want (ita) # values must be 'task_gen' instances (not names!) dependencies = [], # dependencies on env variable contents dep_vars = [], # input files that are implicit, i.e. they are not # stdin, nor are they mentioned explicitly in argv hidden_inputs = [], # output files that are implicit, i.e. they are not # stdout, nor are they mentioned explicitly in argv hidden_outputs = [], # change the subprocess to this cwd (must use obj.input_dir() or output_dir() here) cwd = None, # OS environment variables to pass to the subprocess # if None, use the default environment variables unchanged os_env = None) @feature('command-output') @after_method('init_cmd_output') def apply_cmd_output(self): if self.command is None: raise Errors.WafError("command-output missing command") if self.command_is_external: cmd = self.command cmd_node = None else: cmd_node = self.path.find_resource(self.command) assert cmd_node is not None, ('''Could not find command '%s' in source tree. Hint: if this is an external command, use command_is_external=True''') % (self.command,) cmd = cmd_node if self.cwd is None: cwd = None else: assert isinstance(cwd, CmdDirArg) self.cwd.find_node(self.path) args = [] inputs = [] outputs = [] for arg in self.argv: if isinstance(arg, cmd_arg): arg.find_node(self.path) if isinstance(arg, input_file): inputs.append(arg.node) if isinstance(arg, output_file): outputs.append(arg.node) if self.stdout is None: stdout = None else: assert isinstance(self.stdout, str) stdout = self.path.find_or_declare(self.stdout) if stdout is None: raise Errors.WafError("File %s not found" % (self.stdout,)) outputs.append(stdout) if self.stderr is None: stderr = None else: assert isinstance(self.stderr, str) stderr = self.path.find_or_declare(self.stderr) if stderr is None: raise Errors.WafError("File %s not found" % (self.stderr,)) outputs.append(stderr) if self.stdin is None: stdin = None else: assert isinstance(self.stdin, str) stdin = self.path.find_resource(self.stdin) if stdin is None: raise Errors.WafError("File %s not found" % (self.stdin,)) inputs.append(stdin) for hidden_input in self.to_list(self.hidden_inputs): node = self.path.find_resource(hidden_input) if node is None: raise Errors.WafError("File %s not found in dir %s" % (hidden_input, self.path)) inputs.append(node) for hidden_output in self.to_list(self.hidden_outputs): node = self.path.find_or_declare(hidden_output) if node is None: raise Errors.WafError("File %s not found in dir %s" % (hidden_output, self.path)) outputs.append(node) if not (inputs or getattr(self, 'no_inputs', None)): raise Errors.WafError('command-output objects must have at least one input file or give self.no_inputs') if not (outputs or getattr(self, 'no_outputs', None)): raise Errors.WafError('command-output objects must have at least one output file or give self.no_outputs') cwd = self.bld.variant_dir task = command_output(self.env, cmd, cmd_node, self.argv, stdin, stdout, cwd, self.os_env, stderr) task.generator = self copy_attrs(self, task, 'before after ext_in ext_out', only_if_set=True) self.tasks.append(task) task.inputs = inputs task.outputs = outputs task.dep_vars = self.to_list(self.dep_vars) for dep in self.dependencies: assert dep is not self dep.post() for dep_task in dep.tasks: task.set_run_after(dep_task) if not task.inputs: # the case for svnversion, always run, and update the output nodes task.runnable_status = type(Task.TaskBase.run)(runnable_status, task, task.__class__) # always run task.post_run = type(Task.TaskBase.run)(post_run, task, task.__class__) # TODO the case with no outputs? def post_run(self): for x in self.outputs: x.sig = Utils.h_file(x.abspath()) def runnable_status(self): return self.RUN_ME Task.task_factory('copy', vars=[], func=action_process_file_func) debian/waf-1.6/waflib/extras/batched_cc.py0000664000000000000000000001045412145744415015445 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2006-2010 (ita) """ Batched builds - compile faster instead of compiling object files one by one, c/c++ compilers are often able to compile at once: cc -c ../file1.c ../file2.c ../file3.c Files are output on the directory where the compiler is called, and dependencies are more difficult to track (do not run the command on all source files if only one file changes) As such, we do as if the files were compiled one by one, but no command is actually run: replace each cc/cpp Task by a TaskSlave. A new task called TaskMaster collects the signatures from each slave and finds out the command-line to run. It is only necessary to import this module in the configuration (no other change required) """ import os from waflib import TaskGen, Task, Build, Logs from waflib.TaskGen import extension, feature, before_method, after_method MAX_BATCH = 50 c_str = '${CC} ${CFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} -c ${SRCLST}' #c_str = '${CC} ${CCFLAGS} ${CPPFLAGS} ${_CCINCFLAGS} ${_CCDEFFLAGS} -c ${SRCLST}' c_fun, _ = Task.compile_fun_noshell(c_str) cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} -c ${SRCLST}' #cxx_str = '${CXX} ${CXXFLAGS} ${CPPFLAGS} ${_CXXINCFLAGS} ${_CXXDEFFLAGS} -c ${SRCLST}' cxx_fun, _ = Task.compile_fun_noshell(cxx_str) count = 70000 class batch_task(Task.Task): color = 'RED' after = ['c', 'cxx'] before = ['cprogram', 'cshlib', 'cstlib', 'cxxprogram', 'cxxshlib', 'cxxstlib'] def __str__(self): return '(batch compilation for %d slaves)\n' % len(self.slaves) def __init__(self, *k, **kw): Task.Task.__init__(self, *k, **kw) self.slaves = [] self.inputs = [] self.hasrun = 0 global count count += 1 self.idx = count def add_slave(self, slave): self.slaves.append(slave) self.set_run_after(slave) def runnable_status(self): for t in self.run_after: if not t.hasrun: return Task.ASK_LATER for t in self.slaves: #if t.executed: if t.hasrun != Task.SKIPPED: return Task.RUN_ME return Task.SKIP_ME def run(self): outputs = [] self.outputs = [] srclst = [] slaves = [] for t in self.slaves: if t.hasrun != Task.SKIPPED: slaves.append(t) srclst.append(t.inputs[0].abspath()) self.env.SRCLST = srclst self.cwd = slaves[0].inputs[0].parent.get_bld().abspath() if self.slaves[0].__class__.__name__ == 'c': ret = c_fun(self) else: ret = cxx_fun(self) if ret: return ret for t in slaves: t.old_post_run() from waflib.Tools import c, cxx def hook(name): def n_hook(self, node): task = self.create_task(name, node, node.change_ext('.o')) try: self.compiled_tasks.append(task) except AttributeError: self.compiled_tasks = [task] if not getattr(self, 'masters', None): self.masters = {} self.allmasters = [] if not node.parent in self.masters: m = self.masters[node.parent] = self.master = self.create_task('batch') self.allmasters.append(m) else: m = self.masters[node.parent] if len(m.slaves) > MAX_BATCH: m = self.masters[node.parent] = self.master = self.create_task('batch') self.allmasters.append(m) m.add_slave(task) return task return n_hook extension('.c')(hook('c')) extension('.cpp','.cc','.cxx','.C','.c++')(hook('cxx')) @feature('cprogram', 'cshlib', 'cstaticlib', 'cxxprogram', 'cxxshlib', 'cxxstlib') @after_method('apply_link') def link_after_masters(self): if getattr(self, 'allmasters', None): for m in self.allmasters: self.link_task.set_run_after(m) # Modify the c and cxx task classes - in theory it would be better to # create subclasses and to re-map the c/c++ extensions # for x in ['c', 'cxx']: t = Task.classes[x] def run(self): pass def post_run(self): #self.executed=1 pass def can_retrieve_cache(self): if self.old_can_retrieve_cache(): for m in self.generator.allmasters: try: m.slaves.remove(self) except ValueError: pass #this task wasn't included in that master return 1 else: return None setattr(t, 'oldrun', t.__dict__['run']) setattr(t, 'run', run) setattr(t, 'old_post_run', t.post_run) setattr(t, 'post_run', post_run) setattr(t, 'old_can_retrieve_cache', t.can_retrieve_cache) setattr(t, 'can_retrieve_cache', can_retrieve_cache) debian/waf-1.6/waflib/extras/syms.py0000664000000000000000000000517112145744415014401 0ustar #! /usr/bin/env python # encoding: utf-8 """ this tool supports the export_symbols_regex to export the symbols in a shared library. by default, all symbols are exported by gcc, and nothing by msvc. to use the tool, do something like: def build(ctx): ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib') only the symbols starting with 'mylib_' will be exported. """ import re from waflib.Context import STDOUT from waflib.Task import Task from waflib.Errors import WafError from waflib.TaskGen import feature, after_method class gen_sym(Task): def run(self): obj = self.inputs[0] if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): re_nm = re.compile(r'External\s+\|\s+_(' + self.generator.export_symbols_regex + r')\b') cmd = ['dumpbin', '/symbols', obj.abspath()] else: if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows re_nm = re.compile(r'T\s+_(' + self.generator.export_symbols_regex + r')\b') else: re_nm = re.compile(r'T\s+(' + self.generator.export_symbols_regex + r')\b') cmd = ['nm', '-g', obj.abspath()] syms = re_nm.findall(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT)) self.outputs[0].write('%r' % syms) class compile_sym(Task): def run(self): syms = {} for x in self.inputs: slist = eval(x.read()) for s in slist: syms[s] = 1 lsyms = syms.keys() lsyms.sort() if self.env.DEST_BINFMT == 'pe': self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms)) elif self.env.DEST_BINFMT == 'elf': self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n") else: raise WafError('NotImplemented') @feature('syms') @after_method('process_source', 'process_use', 'apply_link', 'process_uselib_local') def do_the_symbol_stuff(self): ins = [x.outputs[0] for x in self.compiled_tasks] self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins] tsk = self.create_task('compile_sym', [x.outputs[0] for x in self.gen_sym_tasks], self.path.find_or_declare(getattr(self, 'sym_filename', self.target + '.def'))) self.link_task.set_run_after(tsk) self.link_task.dep_nodes = [tsk.outputs[0]] if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME): self.link_task.env.append_value('LINKFLAGS', ['/def:' + tsk.outputs[0].bldpath()]) elif self.env.DEST_BINFMT == 'pe': #gcc on windows takes *.def as an additional input self.link_task.inputs.append(tsk.outputs[0]) elif self.env.DEST_BINFMT == 'elf': self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + tsk.outputs[0].bldpath()]) else: raise WafError('NotImplemented') debian/waf-1.6/waflib/Logs.py0000664000000000000000000001435712145744415013012 0ustar #!/usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2005-2010 (ita) """ logging, colors, terminal width and pretty-print """ import os, re, traceback, sys _nocolor = os.environ.get('NOCOLOR', 'no') not in ('no', '0', 'false') try: if not _nocolor: import waflib.ansiterm except: # optional module for colors on win32, just ignore if it cannot be imported pass import logging # do it after LOG_FORMAT = "%(asctime)s %(c1)s%(zone)s%(c2)s %(message)s" HOUR_FORMAT = "%H:%M:%S" zones = '' verbose = 0 colors_lst = { 'USE' : True, 'BOLD' :'\x1b[01;1m', 'RED' :'\x1b[01;31m', 'GREEN' :'\x1b[32m', 'YELLOW':'\x1b[33m', 'PINK' :'\x1b[35m', 'BLUE' :'\x1b[01;34m', 'CYAN' :'\x1b[36m', 'NORMAL':'\x1b[0m', 'cursor_on' :'\x1b[?25h', 'cursor_off' :'\x1b[?25l', } got_tty = not os.environ.get('TERM', 'dumb') in ['dumb', 'emacs'] if got_tty: try: got_tty = sys.stderr.isatty() except AttributeError: got_tty = False if (not got_tty and os.environ.get('TERM', 'dumb') != 'msys') or _nocolor: colors_lst['USE'] = False def get_term_cols(): return 80 # If console packages are available, replace the dummy function with a real # implementation try: import struct, fcntl, termios except ImportError: pass else: if got_tty: def get_term_cols_real(): """ Private use only. """ dummy_lines, cols = struct.unpack("HHHH", \ fcntl.ioctl(sys.stderr.fileno(),termios.TIOCGWINSZ , \ struct.pack("HHHH", 0, 0, 0, 0)))[:2] return cols # try the function once to see if it really works try: get_term_cols_real() except: pass else: get_term_cols = get_term_cols_real get_term_cols.__doc__ = """ Get the console width in characters. :return: the number of characters per line :rtype: int """ def get_color(cl): if not colors_lst['USE']: return '' return colors_lst.get(cl, '') class color_dict(object): """attribute-based color access, eg: colors.PINK""" def __getattr__(self, a): return get_color(a) def __call__(self, a): return get_color(a) colors = color_dict() re_log = re.compile(r'(\w+): (.*)', re.M) class log_filter(logging.Filter): """ The waf logs are of the form 'name: message', and can be filtered by 'waf --zones=name'. For example, the following:: from waflib import Logs Logs.debug('test: here is a message') Will be displayed only when executing:: $ waf --zones=test """ def __init__(self, name=None): pass def filter(self, rec): """ filter a record, adding the colors automatically * error: red * warning: yellow :param rec: message to record """ rec.c1 = colors.PINK rec.c2 = colors.NORMAL rec.zone = rec.module if rec.levelno >= logging.INFO: if rec.levelno >= logging.ERROR: rec.c1 = colors.RED elif rec.levelno >= logging.WARNING: rec.c1 = colors.YELLOW else: rec.c1 = colors.GREEN return True m = re_log.match(rec.msg) if m: rec.zone = m.group(1) rec.msg = m.group(2) if zones: return getattr(rec, 'zone', '') in zones or '*' in zones elif not verbose > 2: return False return True class formatter(logging.Formatter): """Simple log formatter which handles colors""" def __init__(self): logging.Formatter.__init__(self, LOG_FORMAT, HOUR_FORMAT) def format(self, rec): """Messages in warning, error or info mode are displayed in color by default""" if rec.levelno >= logging.WARNING or rec.levelno == logging.INFO: try: msg = rec.msg.decode('utf-8') except: msg = rec.msg return '%s%s%s' % (rec.c1, msg, rec.c2) return logging.Formatter.format(self, rec) log = None """global logger for Logs.debug, Logs.error, etc""" def debug(*k, **kw): """ Wrap logging.debug, the output is filtered for performance reasons """ if verbose: k = list(k) k[0] = k[0].replace('\n', ' ') global log log.debug(*k, **kw) def error(*k, **kw): """ Wrap logging.errors, display the origin of the message when '-vv' is set """ global log log.error(*k, **kw) if verbose > 2: st = traceback.extract_stack() if st: st = st[:-1] buf = [] for filename, lineno, name, line in st: buf.append(' File "%s", line %d, in %s' % (filename, lineno, name)) if line: buf.append(' %s' % line.strip()) if buf: log.error("\n".join(buf)) def warn(*k, **kw): """ Wrap logging.warn """ global log log.warn(*k, **kw) def info(*k, **kw): """ Wrap logging.info """ global log log.info(*k, **kw) def init_log(): """ Initialize the loggers globally """ global log log = logging.getLogger('waflib') log.handlers = [] log.filters = [] hdlr = logging.StreamHandler() hdlr.setFormatter(formatter()) log.addHandler(hdlr) log.addFilter(log_filter()) log.setLevel(logging.DEBUG) def make_logger(path, name): """ Create a simple logger, which is often used to redirect the context command output:: from waflib import Logs bld.logger = Logs.make_logger('test.log', 'build') bld.check(header_name='sadlib.h', features='cxx cprogram', mandatory=False) bld.logger = None :param path: file name to write the log output to :type path: string :param name: logger name (loggers are reused) :type name: string """ logger = logging.getLogger(name) hdlr = logging.FileHandler(path, 'w') formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.DEBUG) return logger def make_mem_logger(name, to_log, size=10000): """ Create a memory logger to avoid writing concurrently to the main logger """ from logging.handlers import MemoryHandler logger = logging.getLogger(name) hdlr = MemoryHandler(size, target=to_log) formatter = logging.Formatter('%(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.memhandler = hdlr logger.setLevel(logging.DEBUG) return logger def pprint(col, str, label='', sep='\n'): """ Print messages in color immediately on stderr:: from waflib import Logs Logs.pprint('RED', 'Something bad just happened') :param col: color name to use in :py:const:`Logs.colors_lst` :type col: string :param str: message to display :type str: string or a value that can be printed by %s :param label: a message to add after the colored output :type label: string :param sep: a string to append at the end (line separator) :type sep: string """ sys.stderr.write("%s%s%s %s%s" % (colors(col), str, colors.NORMAL, label, sep)) debian/waf-1.6/TODO0000664000000000000000000000044312145744415010747 0ustar Waf 1.6.x --------- * fix the remaining bugs * provide more extensions Can be useful: def bld_command(*k): fun = k[0] name = fun.__name__ from waflib.Build import BuildContext class tmp(BuildContext): cmd = name fun = name return fun @bld_command def foo(ctx): print ctx.env debian/waf-1.6/ChangeLog0000664000000000000000000002527312145744415012041 0ustar NEW IN WAF 1.6.11 ----------------- * Enable custom variables for the boost detection #1089 * Disable the config test execution when detecting boost #1090 * Process moc classes in .cpp files by default #1095 * Apply the chmod attribute to the versioned libraries (vnum) #1097 * Fixed the python detection on OSX #1098 * Changed the win32 color settings for Windows 7 #1099 * Set the default fortran linker for ifort to xiar #1104 NEW IN WAF 1.6.10 ----------------- * Fixed the 'remove' attribute propagation in ant_glob #1086 * Fixed the behavior of recurse(name=xyz) when looking in existing folders * Fixed a problem with include paths in the relocation tool #1078 * Improved the pgicc compiler detection #1080 * Fixed the behavior of 'waf options' #1076 * Process larger java projects #1074 * Remove the ':' from the drives when dealing with foreign files and folders on Win32 * Let the 'subst' feature process a chmod attribute * Added a hook for distutils variable query #1083 NEW IN WAF 1.6.9 ---------------- * Fixed the duplicate moc file creation in slow_qt4 #1047 * Fixed the Visual Studio 2008 projects creation #1033 * Added a workaround to avoid creating include folders not under the build directory #1049 * Added a default virtual folder structure for out-of-tree build files #1053 * Added a way to set variants containing /, for example linux/debug * Added a more intuitive behaviour for conf.setenv() #1062 * Fixed the multiple bibliography processing for tex #1040 * Windows CE detection improvements #1065 * Fixed the library installation on OSX * Fixed the Powerpc/IPhone platform detection * Added an Xcode project generator NEW IN WAF 1.6.8 ---------------- * Fixed a typo in Utils.py affecting Win32 platforms (copystat) #1029 * Fixed a minor bug in the Eclipse project generator * Fixed a typo that prevented Waf from running on Pypy-trunk * Make the xlc/xlc++ compiler detection more accurate by looking at the version number #1022 * Minor perl, python and ruby tool improvements * Better logs for the boost detection #1036 * Fixed a performance issue in Runner.py #1039 * Changed the position of the linker flags #1025 NEW IN WAF 1.6.7 ---------------- * Provide more diagnostic for invalid build groups #914 * Various enhancements to msvs.py * Read MSVC_VERSIONS and MSVC_TARGETS from the command-line * Minor cross-compiler detection fix on msvc.py * Fix the redirections with pipes (waf configure > log) * Do not display runnable_status exceptions when running with -k * Let -k stop at the first runnable_status error and -kk run even further * Merge the add_object extension in the main line (source='file.o') * Make update_outputs more robust with changes in the task definition #1017 * Qt4 detection on Win32 NEW IN WAF 1.6.6 ---------------- * Fix the performance regression related to #974 NEW IN WAF 1.6.5 ---------------- * More documentation * Re-enable the colors for msys * Add the .ui files for the qt4 translations * Fix the conf.check_large_file() test * Fix the conf.check_library() in C++ mode #955 * Improve the latex scanner to avoid depending on generated files #943 * Remove the @file processing from the winrc tasks * Fix the python detection using python-config * Add the missing default includes and defines to the moc command * Improve support for hierarchical go-lang packages #953 * Fix the gfortran verbose flag detection on Windows * Fix the support of fortran import libraries #950 * Added a fix for running with Python 2.4 on Windows #949 * Limited support for IronPython * Support for older Visual Studio versions (VC6) #952 * New waf.bat file #964 * New method ConfigSet.keys * New Visual Studio and Eclipse CTD project generators (waflib/extras) * New lru_cache tool for use with WAFCACHE (waflib/extras) NEW IN WAF 1.6.4 ---------------- * Fix the Python detection on win32 #883 * Optimize the Python file installation #892 * Force +x permissions on installed fortran programs #893 * Qt library detection fixes #895 * Ensure that unit tests are executed only after the symlinks are created * Fix the precedence constraints for classes ending in _task #896 * Support the install_path attribute with add_pcfile #913 * Make the goprograms executable when installed #928 * Allow non-python data files in the waf executable #927 * Enforce a build order based on the scanner results #777, #922 * Multiple msvc detection fixes #907 #910 #923 #924 #926 * Fix the -of flag append with dmd #917 * Boost detection fixes #920 * Support newer javac compilers #921 * Fix the execution on python 2.3 for: "waf update", msvc.py, fc.py * Improve the support for mac applications (demos/mac_app) * Better default regexps in "waf step" * New error check for tasks creating the same nodes or having the same identifiers (waf -v) * New variables conf.env.NO_LOCK_IN_TOP/OUT/RUN for special projects (top='..') * New example on avoiding rebuilds when moving a project (playground/relocate) * Improve go-lang support for cgo-packages (fixes #932) * Fix the progress bar on cmd and msys NEW IN WAF 1.6.3 ---------------- * Fixed the interaction of Fortran configuration tests and WAFCACHE #842 * Various documentation fixes * Set the PYTHONARCHDIR variable for installing python extensions * Fixed the Waf file creation with --zip-type=gz (bunzip2 was not replaced by gzip -d) * Fixed multiple problems in the call to TaskGen.declare_chain(...) #850 * Fixed the task attribute 'vars' which might cause unnecessary rebuilds #852 * Return the value of post_check(...) in conf.check(...) #857 * Rewrite the boost tool (waflib/extras/boost.py) #814, #454, #424 * More fortran file extensions: .for, .FOR #867 * Searching above the root nodes no longer raise exceptions #868 * Msvc detection fixes for non-utf8 encodings #873 * Fixed the destdir processing on Windows #874 * Stop changing the flags on waf -v (make the errors more visible) #875 * Fixed the resource file compilation on Windows #876 * Fixed the vala file installation #881 * New system of plugins for C/C++/Fortran compilers (files named c_* in waflib/extras/) * New examples of interaction between Waf and existing makefiles (playground/) * New names for @before/@after: @before_method/@after_method NEW IN WAF 1.6.2 ---------------- * Support for C# debugging files #797 * Add -relocation-model=pic for shared libraries on ldc * Fixed 'waf dist' for tar files on python 3 #799 * Make the latex scanner recursive #798 * Enable the packing of non-python files in the waf file #802 * Improve the feature sniffing for hybrid programs/libraries #800 * New apidocs + tutorial in Sphinx format * Add the CPPFLAGS from os.environ #803 * Create the java output directory anywhere #806 * Enable the .luac file installation * Process Qt translation files * Detect when the folders were copied and prompt for "waf configure" * Parse_flags for the *-config outputs on windows (backslashes) #811 * Fix the doxygen task build order + improve the dependency scanner #821 * Various msvc fixes #819, #826, #825 * Ported the batch executor to waf 1.6 (batched_cc) * New tools: erlang, scala * Moved conf.multicheck(..) from playground to the library * New parameter to avoid reading the same scripts: bld.recurse(dir, once=True) * Detect invalid method calls in 'waf -v' such as env.append/env.add/env.prepend * New manifest option for jar targets #832 NEW IN WAF 1.6.1 ---------------- * Fixed the method check_waf_version #764 * Fixed the name in ctx.recurse(name) #769 * Stop caching the install tasks and tasks that have no outputs #770 * Fix the log in Context.cmd_and_log() when calling with "quiet" #778 * c_preproc exception when a file has the same name as a directory #777 * 'intltool_po' does not install the .mo files #782 * 'intltool_in' was broken #792 * Bind stderr and stdout to the exception in Context.cmd_and_log #779 * Tasks not rebuilding properly when the 'run' method changes #786 * Print the progress bar information as late as possible #787 * Fix for the FRAMEWORK value processing * Verbose mode should not require the compat15 tools #790 * Let static libraries use other static libraries as in 1.5 #768 * Fix for the boost tool #776 * boost tool update (in playground) #780 * Updated the java tool and examples * New gcj tool in playground * Update the c# tool and examples (playground) #796 * Read external c# libraries #774 * Xelatex support #785 * Rebuild fortran files when .mod files change #766 * docs #781 * Improve the ant_glob behaviour on ctx.root + absolute paths * Fix for glib_mkenums and dbus-binding-tool #795 * New feature 'subst' (see demos/subst) NEW IN WAF 1.6.0 ---------------- General: * Python 3 syntax by default (runs unmodified for 2.6, 2.7, 3.0 and 3.1) * Environment -> ConfigSet * only lists are allowed in ConfigSet * Better Node apis * Utils.load_tool -> Context.load_tool * set_options becomes options * only the build-related commands require a configured project * new variant system + build context commands * removed the pseudo glob in installation methods * eliminate find_sources_in_dirs * node.__class__.bld → node.ctx * bld.new_task_gen(...) disappears, use bld(...) * network updates for waf tools * accept node objects in the source and includes attributes * remove task_gen.allnodes: modify self.source directly * merge the include system for c, c++, d, gas and nasm * allow top == out (no build directory) * merge the Tool/wscript system (detect->configure, set_options->options) * new command "waf list" to list the x for "waf build --targets=x" * rename apply_core -> process_source * rename apply_rule -> process_rule * rename Task.TaskBase.classes -> Task.classes * the modules Utils.py and Logs.py are now independent from the rest of waf (imports) * remove Task.TaskManager and Build.BuildContext.all_task_gen to improve the build group handling * remove program_USELIB, shlib_USELIB staticlib_USELIB support * use tasks for target installation * improve the exception handling (WscriptError was removed, use WafError) * let the commands access node objects * infer the build directory from the lock filename * waf step --file=main.c * post task generators in a lazy manner preview 3: * remove the /W3 flag from msvc default flags * opt.tool_options -> opt.load (now all commands inherit the 'tool' method) * conf.check_tool -> conf.load * do not copy files when creating tar files in 'waf dist' * add zip files in 'waf dist' * fix the behaviour of 'waf distcheck' * preprocessor optimizations * python 2 fixes release candidate: * cache fixes * fortran fixes * python 2 and 3 fixes * docs and docstrings * support for custom waf files and preludes * fix in waflib.Context for overriding command classes * port the doxygen tool * Utils.to_hashtable -> Utils.str2dict * change the thread pool to enable thread pool sharing * fixed a regression on win32 + ansiterm.py + python 3 -> thanks to kesselhaus :-) * various msvc fixes (thanks to Nicolas Mercier) debian/waf-1.6/waf-light0000775000000000000000000000776012145744415012100 0ustar #!/usr/bin/env python # encoding: ISO8859-1 # Thomas Nagy, 2005-2011 """ 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. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "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 THE AUTHOR 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. """ import os, sys VERSION="1.6.11" REVISION="x" INSTALL="x" C1='x' C2='x' cwd = os.getcwd() join = os.path.join if sys.hexversion<0x206000f: raise ImportError('Python >= 2.6 is required to create the waf file') WAF='waf' def b(x): return x if sys.hexversion>0x300000f: WAF='waf3' def b(x): return x.encode() def err(m): print(('\033[91mError: %s\033[0m' % m)) sys.exit(1) def unpack_wafdir(dir): f = open(sys.argv[0],'rb') c = 'corrupt archive (%d)' while 1: line = f.readline() if not line: err('run waf-light from a folder containing waflib') if line == b('#==>\n'): txt = f.readline() if not txt: err(c % 1) if f.readline() != b('#<==\n'): err(c % 2) break if not txt: err(c % 3) txt = txt[1:-1].replace(b(C1), b('\n')).replace(b(C2), b('\r')) import shutil, tarfile try: shutil.rmtree(dir) except OSError: pass try: for x in ['Tools', 'extras']: os.makedirs(join(dir, 'waflib', x)) except OSError: err("Cannot unpack waf lib into %s\nMove waf into a writeable directory" % dir) os.chdir(dir) tmp = 't.bz2' t = open(tmp,'wb') t.write(txt) t.close() try: t = tarfile.open(tmp) except: try: os.system('bunzip2 t.bz2') t = tarfile.open('t') tmp = 't' except: os.chdir(cwd) try: shutil.rmtree(dir) except OSError: pass err("Waf cannot be unpacked, check that bzip2 support is present") for x in t: t.extract(x) t.close() for x in ['Tools', 'extras']: os.chmod(join('waflib',x), 493) if sys.hexversion<0x300000f: sys.path = [join(dir, 'waflib')] + sys.path import fixpy2 fixpy2.fixdir(dir) os.unlink(tmp) os.chdir(cwd) try: dir = unicode(dir, 'mbcs') except: pass try: from ctypes import windll windll.kernel32.SetFileAttributesW(dir, 2) except: pass def test(dir): try: os.stat(join(dir, 'waflib')) return os.path.abspath(dir) except OSError: pass def find_lib(): name = sys.argv[0] base = os.path.dirname(os.path.abspath(name)) #devs use $WAFDIR w=test(os.environ.get('WAFDIR', '')) if w: return w #waf-light if name.endswith('waf-light'): w = test(base) if w: return w err('waf-light requires waflib -> export WAFDIR=/folder') dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) for i in [INSTALL,'/usr','/usr/local','/opt']: w = test(i + '/lib/' + dirname) if w: return w #waf-local dir = join(base, (sys.platform != 'win32' and '.' or '') + dirname) w = test(dir) if w: return w #unpack unpack_wafdir(dir) return dir wafdir = find_lib() sys.path.insert(0, wafdir) if __name__ == '__main__': import waflib.extras.compat15#PRELUDE from waflib import Scripting Scripting.waf_entry_point(cwd, VERSION, wafdir) debian/waf-1.6/DEVEL0000664000000000000000000000322112145744415011036 0ustar previous branches ----------------- old svn repository http://waf.googlecode.com/svn/trunk/ (unused) branch for waf 1.5 http://waf.googlecode.com/svn/branches/waf-1.5/ (read-only, should be moved to git) Main repository for waf 1.6 on http://waf.googlecode.com/git/ ------------------------------------------------------------- waflib the core library waflib/Tools essential waf tools waflib/extras contributed tools which are not included in the waf file by default (except "compat15") build_system_kit examples of build systems that can be created from waf tests various unit tests, most are unused anymore playground experiments and integration tests for the tools in the folder waflib/extras demos integration tests - the folder can be configured as a standalone project demos/* integration tests and examples used as documentation docs documentation docs/sphinx project extracting the docstrings from the source code to create the apidocs Documentation repository on http://docs.waf.googlecode.com/git/ --------------------------------------------------------------- Contains the documentation: API documentation http://docs.waf.googlecode.com/git/apidocs_16/index.html The Waf Book http://docs.waf.googlecode.com/git/book_16/single.html The Waf Book for Waf 1.5 (deprecated) http://docs.waf.googlecode.com/git/book_15/single.html Wiki documentation on http://wiki.waf.googlecode.com/git/ --------------------------------------------------------- Not much to see yet debian/waf-1.6/configure0000775000000000000000000000354712145744415012176 0ustar #! /bin/sh # waf configure wrapper # Fancy colors used to beautify the output a bit. # if [ "$NOCOLOR" ] ; then NORMAL="" BOLD="" RED="" YELLOW="" GREEN="" else NORMAL='\033[0m' BOLD='\033[01;1m' RED='\033[01;91m' YELLOW='\033[00;33m' GREEN='\033[01;92m' fi EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_ERROR=2 EXIT_BUG=10 CUR_DIR=$PWD #possible relative path WORKINGDIR=`dirname $0` cd $WORKINGDIR #abs path WORKINGDIR=`pwd` cd $CUR_DIR # Checks for WAF. Honours $WAF if set. Stores path to 'waf' in $WAF. # Requires that $PYTHON is set. # checkWAF() { printf "Checking for WAF\t\t\t: " #installed miniwaf in sourcedir if [ -z "$WAF" ] ; then if [ -f "${WORKINGDIR}/waf" ] ; then WAF="${WORKINGDIR}/waf" if [ ! -x "$WAF" ] ; then chmod +x $WAF fi fi fi if [ -z "$WAF" ] ; then if [ -f "${WORKINGDIR}/waf-light" ] ; then ${WORKINGDIR}/waf-light --make-waf WAF="${WORKINGDIR}/waf" fi fi #global installed waf with waf->waf.py link if [ -z "$WAF" ] ; then WAF=`which waf 2>/dev/null` fi # neither waf nor miniwaf could be found if [ ! -x "$WAF" ] ; then printf "$RED""not found""$NORMAL""\n" echo "Go to http://code.google.com/p/waf/" echo "and download a waf version" exit $EXIT_FAILURE else printf "$GREEN""$WAF""$NORMAL""\n" fi } # Generates a Makefile. Requires that $WAF is set. # generateMakefile() { cat > Makefile << EOF #!/usr/bin/make -f # Waf Makefile wrapper WAF_HOME=$CUR_DIR all: #@$WAF build all-debug: @$WAF -v build all-progress: @$WAF -p build install: $WAF install --yes; uninstall: $WAF uninstall clean: @$WAF clean distclean: @$WAF distclean @-rm -rf build @-rm -f Makefile check: @$WAF check dist: @$WAF dist .PHONY: clean dist distclean check uninstall install all EOF } checkWAF generateMakefile "${WAF}" configure $* exit $? debian/ns3-doc.doc-base.ns3-doxygen0000664000000000000000000000037411766047442014231 0ustar Document: ns3-doxygen Title: ns-3 API documentions Author: The ns3 Project Abstract: ns-3 API documentions from src by doxygen Section: Programming/ns3 Format: HTML Index: /usr/share/doc/ns3/doxygen/index.html Files: /usr/share/doc/ns3/doxygen/*.html debian/patches/0000775000000000000000000000000012146201264010615 5ustar debian/patches/waf_in_applications_is_not_link.diff0000664000000000000000000000044112145736532020061 0ustar Index: ns3/ns-3.17/src/applications/waf =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ ns3/ns-3.17/src/applications/waf 2013-05-19 01:25:35.127534186 +0800 @@ -0,0 +1 @@ +exec "`dirname "$0"`"/../../../../waf "$@" debian/patches/test-lockfile.patch0000664000000000000000000000102312145736532014411 0ustar Index: ns3/ns-3.17/test.py =================================================================== --- ns3.orig/ns-3.17/test.py 2013-05-19 01:25:20.335534327 +0800 +++ ns3/ns-3.17/test.py 2013-05-19 01:25:20.331534327 +0800 @@ -565,7 +565,7 @@ # and use that result. # def read_waf_config(): - for line in open(".lock-waf_" + sys.platform + "_build", "rt"): + for line in open(".lock-waf_build", "rt"): if line.startswith("top_dir ="): key, val = line.split('=') top_dir = eval(val.strip()) debian/patches/no_rpath_for_mpi.diff0000664000000000000000000000135212145736532015007 0ustar Index: ns3/ns-3.17/src/mpi/wscript =================================================================== --- ns3.orig/ns-3.17/src/mpi/wscript 2013-05-19 01:25:25.667534276 +0800 +++ ns3/ns-3.17/src/mpi/wscript 2013-05-19 01:25:25.659534276 +0800 @@ -21,9 +21,6 @@ if mpi: conf.env.append_value('DEFINES_MPI', 'NS3_MPI') conf.env['ENABLE_MPI'] = True - for libpath in conf.env.LIBPATH_MPI: - if 'mpi' in libpath: - conf.env.append_value('LINKFLAGS_MPI', '-Wl,-rpath,'+libpath) conf.report_optional_feature("mpi", "MPI Support", True, '') else: conf.report_optional_feature("mpi", "MPI Support", False, 'mpic++ not found') debian/patches/series0000664000000000000000000000012312146201264012026 0ustar no_rpath_for_mpi.diff add_vnum_to_shared.diff waf_in_applications_is_not_link.diff debian/patches/add_vnum_to_shared.diff0000664000000000000000000000067612145736532015317 0ustar Index: ns3/ns-3.17/wscript =================================================================== --- ns3.orig/ns-3.17/wscript 2013-05-19 01:25:30.291534232 +0800 +++ ns3/ns-3.17/wscript 2013-05-19 01:25:30.287534232 +0800 @@ -57,7 +57,7 @@ wutils.APPNAME = APPNAME # we don't use VNUM anymore (see bug #1327 for details) -wutils.VNUM = None +wutils.VNUM = "0.0.0" # these variables are mandatory ('/' are converted automatically) top = '.' debian/patches/manual-man-error.diff0000664000000000000000000000132312145730560014630 0ustar Index: ns3/ns-3.17/doc/manual/source/attributes.rst =================================================================== --- ns3.orig/ns-3.17/doc/manual/source/attributes.rst 2012-06-13 15:54:48.542537523 +0800 +++ ns3/ns-3.17/doc/manual/source/attributes.rst 2012-06-13 16:08:55.726738480 +0800 @@ -858,8 +858,11 @@ sudo apt-get install libgtk2.0-0 libgtk2.0-dev -To check whether it is configured or not, check the output of the step::: -./waf configure --enable-examples --enable-tests +To check whether it is configured or not, check the output of the step: + +:: + + ./waf configure --enable-examples --enable-tests ---- Summary of optional NS-3 features: Threading Primitives : enabled debian/duplicate-files.sh0000664000000000000000000000031312115122661012570 0ustar #!/bin/sh TMP1=doc-md5 TMP2=doc-md5.sort CURDIR=$(pwd) cd $1 find -type f -maxdepth 1 -exec md5sum {\} \; > $TMP1 sort $TMP1 > $TMP2 python ${CURDIR}/debian/duplicate-files.py $TMP2 rm -rf $TMP1 $TMP2