#!/opt/rh/rh-python36/root/usr/bin/python # Copyright (C) 2017,2018 # Associated Universities, Inc. Washington DC, USA. # # This library is free software; you can redistribute it and/or modify it # under the terms of the GNU Library General Public License as published by # the Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This library is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public # License for more details. # # You should have received a copy of the GNU Library General Public License # along with this library; if not, write to the Free Software Foundation, # Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. # # Correspondence concerning AIPS++ should be addressed as follows: # Internet email: aips2-request@nrao.edu. # Postal address: AIPS++ Project Office # National Radio Astronomy Observatory # 520 Edgemont Road # Charlottesville, VA 22903-2475 USA ############################################################################################## ############################################################################################## #### #### (1) move generated files beneath build #### ############################################################################################## ############################################################################################## """CASA Python Module This is a standard python module that provides CASA tools and tasks without regular CASA's bespoke CLI. """ from __future__ import division, print_function classifiers = """\ Development Status :: 3 - Alpha Intended Audience :: Developers License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) Programming Language :: Python :: 2.7 Programming Language :: C++ Topic :: Software Development Topic :: Scientific/Engineering :: Astronomy Topic :: Software Development :: Libraries :: Python Modules Operating System :: MacOS :: MacOS X Operating System :: POSIX """ from distutils.ccompiler import new_compiler, CCompiler from distutils.sysconfig import customize_compiler from distutils.core import setup, Extension from distutils.ccompiler import get_default_compiler from distutils.ccompiler import show_compilers from distutils.command.build_ext import build_ext from distutils.errors import DistutilsExecError, CompileError from distutils.dir_util import copy_tree, remove_tree from distutils.core import Command from distutils.util import spawn from subprocess import Popen, PIPE from subprocess import call as Proc from textwrap import dedent from shutil import copy2 import subprocess import sysconfig import platform import pickle import errno import time import sys import re import os import io from os import listdir from os.path import isfile, join, islink from itertools import chain module_name = 'casatools' pyversion = float(sys.version_info[0]) + float(sys.version_info[1]) / 10.0 xml_jar_file = 'xml-casa-assembly-1.1.jar' if pyversion < 3: str_encode = str str_decode = str def pipe_decode(output): return output else: def str_encode(s): return bytes(s,sys.getdefaultencoding()) def str_decode(bs): return bs.decode(sys.getdefaultencoding(),"strict") def pipe_decode(output): if isinstance(output,bytes) or isinstance(output,bytearray): return str_decode(output) elif isinstance(output,tuple): return (str_decode(output[0]),str_decode(output[1])) else: return ("","") if sys.platform == 'darwin': def islib(l): return l.endswith('.dylib') elif sys.platform == 'linux2' or sys.platform == 'linux': def islib(l): # 'lib_....so return l.find('.so') > 3 else: sys.exit("oops, had not planned on building on %s" % sys.platform) boost_exclusions = [ 'Merger.cc', 'PycValueHolder.cc', 'PycBasicData.cc', 'PycRecord.cc', 'PycArray.cc', 'PycExcp.cc', 'PycArrayNP.cc', 'PycImport.cc' ] a_priori_exclusions = ['tTableRecord.cc','tXMLToRecord.cc','tArrayIteratorSTL.cc','tStokesConverter.cc','value_variant.cc','tSymLink.cc','tImageExpr2.cc','tRefTable.cc','tPBMath1DEVLA.cc','SingleDishMS_GTest.cc','dRGBTestPattern.cc','tMSReader.cc','tChoice.cc','tCFCache.cc','tImageAnalysis.cc','tPBTable.cc','tLatticeExprNode.cc','tRecursiveVi2LayersWithCal_GT.cc','tCopy.cc','tKJones.cc','tFlagAgentDisplay.cc','tArrayIO3.cc','tTime.cc','tBeamSquint.cc','tImageDecomposer.cc','tStatWtTVI.cc','tCalSolVi2Organizer_GT.cc','tReadBigBDF.cc','tComponentType.cc','tFITSErrorImage.cc','tStatisticsUtilities.cc','tAppInfo.cc','LineFinder_GTest.cc','tMSDataDescBuffer.cc','tMFrequency.cc','tLockFile.cc','tWCBox.cc','tLatConvEquation.cc','tList.cc','dDataSelection.cc','tmeas.cc','tPrimes.cc','VisibilityIteratorImplAsync2.cc','tReadAsciiTable.cc','tImageUtilities.cc','FillMetadata.cc','tSimpleSimVi2_GT.cc','MSCheckerTest.cc','tMSScanGram.cc','tStdLogical.cc','tImageRegrid.cc','tObjectPool.cc','tCoordinateSystem.cc','tLatticePerf.cc','SingleDishMSFiller_GTest.cc','tFFTServer2.cc','tUnit.cc','tRegex2.cc','tFlagAgentTimeFreqCrop.cc','tCTIter.cc','tRegionHandler.cc','tRecordTransformable.cc','tFitGaussian.cc','tPrecision.cc','tVirtColEng.cc','tTableLock.cc','tRecordDesc.cc','tHashMapIter.cc','dVarRefMdirCol.cc','tLatticeApply2.cc','dAveragingTime.cc','tStokesImageUtil.cc','tImageExprParse_addDir.cc','tLEL.cc','tVLADiskInput.cc','tfitsskip_hdu.cc','tLatticeRegion.cc','tMSAntennaGram3.cc','tMatrixMath.cc','tVLATapeInput.cc','tfits_ascTbl2.cc','AtmosphereTest.cc','dPagedArray.cc','tFluxStandard4.cc','tFlagger.cc','tFluxStandard3.cc','tMaskArrExcp.cc','tAttribute_Gtest.cc','tMultiHDF5.cc','tError.cc','tVisCal_GT.cc','tImageFFT.cc','asdm2msfillertask_cmpt.cc','dGridPlacementMultipleRuns.cc','tSIIterBot.cc','tRegionTextParser.cc','tSynthesisUtils.cc','tMeasureHolder.cc','tImager.cc','tHanningSmooth.cc','tIDL.cc','tByteSinkSource.cc','tfits_binTbl1.cc','tAipsrcValue.cc','tDataType.cc','tImagePolarimetry.cc','makeAsdmIndex.cc','dTimeIteration.cc','tLatticeIterator.cc','tFunctionHolder.cc','tCalStats7.cc','tTiledShape.cc','tLCRegion.cc','tMArrayUtil.cc','tArrayBase.cc','tSort_1.cc','tTiledDataStMan.cc','tBucketCache.cc','tPtrHolder.cc','tLinearXform.cc','tSynthesisImager.cc','tIAU2000.cc','dAutoDiff.cc','SDMaskHandler_GTest.cc','3DWindow.cc','tFitter5689.cc','tLatticeExpr2Node.cc','tComponentList.cc','ascii2Table.cc','tUVContSubTVI.cc','tExtendSpecifier.cc','dPanelDisplay.cc','tLCMask.cc','tMSTimeGram.cc','tMutex.cc','tExprUnitNode.cc','tNutation.cc','tFluxStandard.cc','tLatticeExpr3Node.cc','QtParamGUI.cc','tfits2.cc','tTblAsRaster.cc','tArrayOpsDiffShapes.cc','casadrawer.cc','tAsdmStMan.cc','tSlice.cc','tTiledBool.cc','tLCExtension.cc','tMSSummary.cc','tStatWt2.cc','dLatticeAsVector.cc','tChannelAverageTVI.cc','tLCPolygon.cc','tImageExprGram.cc','dAveragingChannel.cc','tHyperPlane.cc','dSymbol.cc','tIPosition.cc','tTapeIO.cc','tTabularCoordinate.cc','dVSCEngine.cc','tMeasurementSet.cc','tSpectralCoordinate.cc','VisBufferImplAsync2.cc','tImageConvolver.cc','tBinTable.cc','tSpectralIndex.cc','tfits3.cc','tStack.cc','VLAT2.cc','tExtendImage.cc','tLinearFitSVD.cc','tSSMStringHandler.cc','tMaskArrMath2.cc','tMDirection.cc','tArrayLogical.cc','tFITSKeywordUtil.cc','tfits2ms.cc','dInterpolate1D.cc','tHashMapIO.cc','tGaussianND.cc','tTSMShape.cc','tFeather.cc','tRecursiveVi2Layers_GT.cc','tTableQuantum.cc','tSmooth.cc','tMMapIO.cc','dCoordinates.cc','tSakuraArrayConverter.cc','tfits_binTbl2.cc','ParamPanel.cc','dImageStatistics.cc','tHDF5DataSet.cc','CrashReportPoster.cc','tString.cc','tArrayAsRaster.cc','tPrecTimer.cc','tEarthMagneticMachine.cc','Subtable.cc','tCTTimeInterp1.cc','tTiledCellStMan.cc','dImageSummary.cc','tVisModelData.cc','tTiledStMan.cc','tCalibraterSolve_GT.cc','tTable_2.cc','tCoordinateUtil.cc','tTableIter.cc','tGaussianShape.cc','SlideEditor.cc','tBitVector.cc','tGaussianDeconvolver.cc','dTwoSidedShape.cc','tDisplayOptions.cc','tVisModelDataRefim.cc','tfits_imgExt2.cc','Subtables.cc','dImageInterface.cc','tGenSort.cc','tPBMath2D.cc','tTypes.cc','tTrVI2.cc','tMEarthMagnetic.cc','tMSDerivedValues.cc','dMeasure.cc','dDBusViewerProxy.cc','tCOWPtr.cc','type_record.cc','dImageHistograms.cc','tArrayIter.cc','parasdm2MS.cc','dRegionFile.cc','SampleReaderDemo.cc','PointingDirectionCache_Test.cc','tValueHolder.cc','dRemoveAxes.cc','tLatticeConvolver.cc','tCEMemModel.cc','tMSTransformIterator.cc','tTableInfo.cc','tAipsrc.cc','tLogTransformedPolynomialSpectralElement.cc','tStatWt.cc','tMVAngle.cc','tCanonicalConversion.cc','tHashMap.cc','tMSFieldGram.cc','tLogging.cc','tCalInterpolation.cc','MatrixMath.cc','tSkyComponentFactory.cc','tSpectralFit.cc','ImageMaskHandler_Gtest.cc','tFITSExtImage.cc','tUVSub.cc','tAnnRotBox.cc','tZScoreCalculator.cc','flagger_cmpt.cc','dQtDataManager.cc','tPoolStack.cc','ValuePanel.cc','tImageRegion.cc','dSparseDiff.cc','tQueue.cc','tImageFitter.cc','tGaussianConvert.cc','tVisVectorJonesMueller_GT.cc','tImageCollapser.cc','tVPSkyJones.cc','tImageStatistics.cc','dGLDemo.cc','tScalarRecordColumn.cc','tRecordGram.cc','tFFT2D.cc','tRegex_1.cc','tLatticeAddNoise.cc','tMArray.cc','tArrayMath.cc','tLatticeCache.cc','tLatticeIndexer.cc','VisBufferAsyncWrapper2.cc','tAWPFTM.cc','tVectorSTLIterator.cc','tScaledComplexData.cc','tEnvVar.cc','tMBaseline.cc','MirTypeAssert.cc','tOrdMap.cc','tAttribute.cc','tCoordinate.cc','dConstraints.cc','tAttValPoi.cc','tFit2D.cc','tSampledFunctional.cc','tImageFit1D.cc','dWorldMap.cc','tConversion.cc','tBitFlagsEngine.cc','tLCPixelSet.cc','tRebinImage.cc','nISMBucket.cc','tExprGroup.cc','tFFTServer.cc','tRIorAPArray.cc','tHDF5Lattice.cc','tArray.cc','tCompoundFunction.cc','tMArrayMath.cc','tHDF5Image.cc','tFunctors.cc','tAnnRectBox.cc','tMath.cc','tfits_priGrp.cc','dExportRangeRightBottom.cc','tUDFMSCal.cc','tfitsread_data.cc','tSort.cc','Colorbar.cc','tMSColumns.cc','tLatticeApply.cc','use_EditlineGuiProxy.cc','tFlagAgentClipping.cc','tStokes.cc','FluxStandard2_GTest.cc','tHDF5Iterator.cc','tRowCopier.cc','tStokesUtil.cc','tVisCalGlobals_GT.cc','tCompare.cc','tFlagAgentBase.cc','tAnnText.cc','tBucketMapped.cc','tLatticeFractile.cc','tLatticeStatistics.cc','tParam.cc','dM1950_2000.cc','tImageProxy.cc','tWCExtension.cc','tMeasMath.cc','tMSSpwGram.cc','dLSQFit.cc','Antennas.cc','tTableVector.cc','tCalStats3.cc','tRecordExpr.cc','dCEMemModel.cc','AveragingTvi2_Test.cc','tImageStatistics2.cc','tTableLockSync.cc','tImageSourceFinder.cc','tPowerLogarithmicPolynomial.cc','tMappedIO.cc','dPSWorldCanvasApp.cc','AlignMemory.cc','tLSQaips.cc','tConstants.cc','tUVWMachine.cc','tNewCalTable.cc','tSakuraAlignedArray.cc','dExportRangeRightTop.cc','dExportRangePipeline.cc','tStArrayFile.cc','tBucketBuffered.cc','tRegionManager.cc','PythonInterpreter.cc','tArrayUtilPerf.cc','tConvertArray.cc','dExportRangeInternal.cc','tRegularFile.cc','dAveraging.cc','tfitsskip_all.cc','tQuantum.cc','tVAXConversion.cc','tArrayMath2.cc','tCombinatorics.cc','tViff.cc','tRebinLattice.cc','tAntennaResponses.cc','tSkyCompRep.cc','harvestrr.cc','tRFCubeLattice.cc','tTableLockSync_2.cc','tFITSImage.cc','tTiledShapeStMan.cc','tPJones_GT.cc','tExprNodeSet.cc','tMemory.cc','tVector.cc','tViiLayerFactory_GT.cc','tTableTrace.cc','tMSMetaData.cc','tfitsskip.cc','tFitterEstimatesFileParser.cc','tHDF5Record.cc','CrashReporter.cc','tLELAttribute.cc','tKJones_GT.cc','tVelocityMachine.cc','tQVector.cc','tLCUnion.cc','tSPolynomial.cc','tLCConcatenation.cc','tMSFITSInput.cc','tMSMetaInfoForCal_GT.cc','tDlHandle.cc','tArrayUtil.cc','tAgentFlagger.cc','3DController.cc','tAnnLine.cc','tCombiFunction.cc','LineFindingUtils_GTest.cc','tImageConcat.cc','tImageTransposer.cc','tCountedPtr.cc','dLogging2.cc','dLattice.cc','tEarthField.cc','tArrayIter1.cc','tTempImage.cc','DemoDummy.cc','tSubLattice.cc','tMVPosition.cc','SofaTest.cc','tTiledEmpty.cc','tTileStepper.cc','tLCLELMask.cc','tGaussianMultipletSpectralElement.cc','FluxStandard_GTest.cc','tImageExpr3Gram.cc','tSparseDiff.cc','tCompositeNumber.cc','tTable.cc','tLCIntersection.cc','dPagedImage.cc','tSTLMath.cc','tCTGenericFill.cc','tArrayAccessor.cc','tMaskArrLogi.cc','tJsonValue.cc','dOverPlot.cc','tLatticeHistograms.cc','tFITSQualityImage.cc','tImageInputProcessor.cc','dExportRangeLeftTop.cc','tImageAnalysis2.cc','tLatticeUtilities.cc','tTblAsXY.cc','tMedianSlider.cc','tMSPolBuffer.cc','tStatAcc.cc','tCalStats0.cc','tArrayColumnCellSlices.cc','tGlinXphJones_GT.cc','tDataConversion.cc','tBinarySearch.cc','tFlagAgentElevation.cc','tAlgoPClark.cc','tFlagAgentExtension.cc','tLCPolygon2.cc','tGaussianBeam.cc','tTiledCellStM_1.cc','ProtoVR.cc','tTaQLNode.cc','tAnnVector.cc','VisBufferImpl.cc','tBoxedArrayMath.cc','LUdecomp.cc','dLogging.cc','synthesisparsync_cmpt.cc','tAnnCircle.cc','tTiledShapeStM_1.cc','tExprNodeUDF.cc','AWConvFunc2.cc','tTableExprData.cc','tByteSink.cc','tImagePrimaryBeamCorrector.cc','tImageExpr2Gram.cc','tMultiFile.cc','tJsonOut.cc','tMeasJPL.cc','MirExceptions.cc','tDiagonal.cc','tChannelAverageTransformEngine_GT.cc','tTableDesc.cc','dQtPlotter.cc','tMMueller_GT.cc','tqlayout.cc','tPolynomial.cc','tCTPatchedInterp.cc','tProfileFit1D.cc','tLCEllipsoid.cc','tHanningSmoothTVI.cc','dLegend.cc','tFitToHalfStatistics.cc','tSakuraUtils.cc','tApplicator.cc','tPointComponent.cc','tInterpolate2D.cc','tConcatTable3.cc','tQualityCoordinate.cc','tVanVleck.cc','tGridFT.cc','dOverPlot2Files.cc','tLinearCoordinate.cc','MirVisReader.cc','tCalLibraryParse.cc','tTempLattice.cc','tClarkCleanLatModel.cc','tMSFieldEphem.cc','tTableDescHyper.cc','tMaskArrIO.cc','dVirtColEng.cc','tRegex.cc','tTiledLineStepper.cc','SDPosInterpolator_GTest.cc','tTable_3.cc','tPowerLogPolynomialSpectralElement.cc','tMathNaN.cc','t2xReadASDM.cc','tImageExprParse.cc','tSlidingArrayMath.cc','tLargeFilebufIO.cc','tCTSelection.cc','tFITSImgParser.cc','tGeometry.cc','tJsonKVMap.cc','tVSCEngine.cc','tCurvedLattice2D.cc','tGaussian1D.cc','tLatticeConcat.cc','tInterpolate1D.cc','tfits_ascTbl.cc','tTypeIO.cc','tDerivedMSCal.cc','MsFactory.cc','tMeasure.cc','tComponentImager.cc','tSinusoid1D.cc','tLogSink.cc','tFITS.cc','tConvolver.cc','tForwardCol.cc','tMSSelection.cc','tArrayMathPerf.cc','tRegister.cc','dOverIterationPlot.cc','tStMan.cc','tAipsIOCarray.cc','tBucketFile.cc','tComplex.cc','AsynchronousInterface2.cc','tInput.cc','tConversionPerf.cc','tFile.cc','TestUtilsTVI.cc','tCasacRegionManager.cc','tLineFinder.cc','tfitsreader.cc','tTableGram.cc','tImageStatsCalculator.cc','casaparamgui.cc','tGaussianComponent.cc','PolAverageTVI_GTest.cc','tPagedImage2.cc','tConstantSpectrum.cc','3v.cc','tLatticeExpr3.cc','3DDisplayData.cc','tVLALogicalRecord.cc','dGridPlacementMultiplePlots.cc','tConvert.cc','tCalibraterSolveSimData_GT.cc','tIncrementalStMan2.cc','tTableRow.cc','tModcompConversion.cc','tCompareBoxedPartial.cc','IDIndex.cc','tMemoryStMan.cc','tCasaImageBeamSet.cc','accumulateFromGrid.cc','tTiledFileAccess.cc','tALMAAperture.cc','tLECanonicalConversion.cc','tMSConcat.cc','tMatrixMathLA.cc','tMathFunc.cc','tFuncExpression.cc','tWCEllipsoid.cc','tNonLinearFitLM.cc','tCLPatchPanel.cc','Viff.cc','tStandardStMan.cc','tFunctionOrder.cc','tFrequencyAligner.cc','tTableStreamReader.cc','tAttVal.cc','tDiskShape.cc','tHostInfo.cc','tAutoDiff.cc','dGaussianND.cc','tDirectionCoordinate.cc','tcal_cmpt2.cc','tMSCalEnums.cc','tAxesSpecifier.cc','tRecordGramTable.cc','tAutoflag.cc','tCasarc01.cc','dExportRangeLeftBottom.cc','tHingesFencesStatistics.cc','harvestrn.cc','tImageInfo.cc','tMemoryTrace.cc','tBlock.cc','tParAngleMachine.cc','tCasaImageOpener.cc','tTable_4.cc','tWCLELMask.cc','tSTLIO.cc','tDJones_GT.cc','tFringeJones_GT.cc','FortranizedLoopsFromGrid.cc','tImage2DConvolver.cc','tMappedArrayEngine.cc','dLatticeAsRaster.cc','tSimButterworthBandpass.cc','tMuvw.cc','tByteIO.cc','tTiledColumnStMan.cc','tPixelCurve1D.cc','DataLoadingBuf.cc','tForwardColRow.cc','tMSUvDistGram.cc','tMSIter.cc','tLatticeTwoPtCorr.cc','tRegionTextList.cc','tCalStats6.cc','tReadAsciiTable2.cc','tCalStats1.cc','tPhaseShiftingTVI.cc','tPBMath.cc','tConvolutionEquation.cc','tLatticeStatsDataProvider.cc','tLattStatsSpecialize.cc','tInterpolateArray1D.cc','tLimbDarkenedDiskShape.cc','dMultiplePlotTypes.cc','dRetypedArrayEngine.cc','tTableCopy.cc','tConcatTable2.cc','dArrayAccessor.cc','dRGBWCRaster.cc','tFlagDataHandler.cc','tExtendLattice.cc','dProfile2dDD.cc','tDynBuffer.cc','tFJones.cc','tVectorKernel.cc','tSubImage.cc','tProfileFitterEstimatesFileParser.cc','tLatticeFit.cc','tColumnsIndexArray.cc','tClassicalStatistics.cc','tArrayAndDrawing.cc','tTiledDataStM_1.cc','tHistAcc.cc','tAnnAnnulus.cc','MakeMS.cc','tMSAntennaGram2.cc','tSolveDataBuffer_GT.cc','dTimeColorization.cc','tSimOrdMap.cc','tArrayIO2.cc','dPointShape.cc','tFITSExtImageII.cc','tBlockTrace.cc','tVisibilityIterator.cc','tCalibrater.cc','tVisibilityIteratorAsync.cc','tFITSSpectralUtil.cc','tStringDistance.cc','tfits5.cc','tLabelandFindRegions.cc','dMUString.cc','importmiriad.cc','dSpectralModel.cc','dExportRange.cc','tTable_1.cc','tArrayColumnSlices.cc','tLELSpectralIndex.cc','tTimer.cc','tCalStats5.cc','tStatisticsAlgorithmFactory.cc','tShadow.cc','tObjectStack.cc','tExprGroupArray.cc','tPath.cc','tSlicer.cc','tLCComplement.cc','tLCDifference.cc','tClarkCleanModel.cc','tStMan1.cc','tConcatRows.cc','tMSFitsSelection.cc','tMeasIERS.cc','tLUdecomp.cc','dImagingWeightViaGridFT.cc','tTableCopyPerf.cc','tOrdMap2.cc','tMSKeys.cc','tLELMedian.cc','tFileIO.cc','tIncrementalStMan.cc','tArrayIO.cc','ImageMaskHandlerTest.cc','tMSCorrGram.cc','tFilebufIO.cc','tStringArray.cc','paramgui_python.cc','tCompressComplex.cc','tConcatTable.cc','tMSMainBuffer.cc','tFlagAgentSummary.cc','FortranizedLoopsToGrid.cc','tPointShape.cc','tObjectID.cc','dTimeColorizationAveraging.cc','tAipsIO.cc','tPerfTransform.cc','CalTableFromAIPS.cc','tFlagAgentQuack.cc','tCalStats4.cc','dPSLatticeAsRaster.cc','dFunction.cc','dCOWptr.cc','tSepImageConvolver.cc','tMSFITSOutput.cc','tGaussian3D.cc','tMaskedArray.cc','tImageExpr.cc','dVLAArchiveInput.cc','tRNG.cc','tMSFieldBuffer.cc','tReadSeqBDFs.cc','tEVLAAperture.cc','tLatticeFFT.cc','SDAlgorithmTest.cc','tArrayPosIter.cc','tDirectoryIterator.cc','tFITSDateUtil.cc','tVirtualTaQLColumn.cc','tReadAllBDFs.cc','interrupt_python.cc','tDirectory.cc','tcal_cmpt.cc','tCalIntpMatch.cc','tTblAsContour.cc','tSumPerformance.cc','tImageMetaData.cc','VisibilityIterator_Test.cc','tTableAccess.cc','tTableKeywords.cc','SDDoubleCircleGainCalImpl_GTest.cc','tStokesCoordinate.cc','tMVTime.cc','tFunctionWrapper.cc','tFallible.cc','FluxStandardTest.cc','tVisIter.cc','tFlagAgentManual.cc','EphemObjFluxStandard_GTest.cc','dSkyCompBase.cc','tVisVectorJonesMueller.cc','tImageAttrHandler.cc','tFITSHistoryUtil.cc','dImageMoments.cc','MirFiller.cc','tIBMConversion.cc','tTabularSpectrum.cc','tSSMAddRemove.cc','tCompressFloat.cc','tPagedArray.cc','dDBus.cc','tPagedImage.cc','version2.cc','tfits1.cc','tObsInfo.cc','dExportPlot.cc','tMeasComet.cc','dGridPlacement.cc','tHDF5File.cc','VisibilityProcessing_Test.cc','dTimeAveragingIteration.cc','bimafiller.cc','tPixonProcessor.cc','tStatisticsTypes.cc','tMemoryTable.cc','tVLABuffer.cc','tFlagAgentShadow.cc','tMSFeedGram.cc','tIncCEMemModel.cc','tMSAntennaGram.cc','tAnnEllipse.cc','value_record.cc','tChebyshev.cc','tScaledArrayEngine.cc','tCalStats2.cc','tLCStretch.cc','tMaskArrMath1.cc','tfits4.cc','tAnnCenterBox.cc','tMIRIADImage.cc','tLoggerHolder.cc','tColumnsIndex.cc','tProjection.cc','tDisplayEvent.cc','dOverLeftRightPlot.cc','tCCList.cc','tMaskArrMath0.cc','tAnnSymbol.cc','tImageProfileFitter.cc','tWCUnion.cc','tFlagAgentRFlag.cc','SingleDishSkyCal_GTest.cc','tMSBin.cc','tPoisson.cc','tFTMachine.cc','tMFFileIO.cc','tSpectralFitter.cc','tConstantND.cc','tLinearSearch.cc','dMultichannelRaster.cc','tLinAlgebra.cc','t_priArr_imgExt.cc','tQuality.cc','tRefRows.cc','tFluxStandard2.cc','tRFASelector.cc','tLatticeExpr2.cc','MSChecker_Gtest.cc','tSubImageFactory.cc','dDBusSession.cc','tMsPlot.cc','tSynthesisImagerVi2.cc','tGaussian2D.cc','tExprNode.cc','tLatticeStepper.cc','conversions.cc','tImageMoments.cc','tHDF5.cc','tRegriddingTVI.cc','tFlagIndex.cc','VisibilityIterator_Gtest.cc','tChauvenetCriterionStatistics.cc','tPixelValueManipulator.cc','tLSQFit.cc','type_variant.cc','tReadParBDFs.cc','dNBody.cc','tImageEmpty.cc','tLCPagedMask.cc','tArrayMathTransform.cc','tLatticeLocker.cc','tLatticeSlice1D.cc','tLargeFileIO.cc','tRecord.cc','tTableMeasures.cc','tLatticeExpr.cc','tQuantumHolder.cc','tDisplayTool.cc','tNewCalTableIterNick.cc','tImageBeamSet.cc','DOmirfiller.cc','tDefaultValue.cc','tCalStatsTab.cc','tLorentzianSpectralElement.cc','CTSelection.cc','tLCSlicer.cc','tLatticeMathUtil.cc','tAnnPolygon.cc','tMedianSmooth.cc','tArrayLattice.cc','dProgressMeter.cc','PGPlotterLocal.cc', ] a_priori_directory_exclusions = [ ] def flatmap(f, items): return chain.from_iterable(map(f, items)) def isexe(f): return os.path.isfile(f) and os.access(f, os.X_OK) def clean_args(l): return [a for a in l if len(a) > 0] def mkpath(path): try: os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise ## https://stackoverflow.com/questions/14320220/testing-python-c-libraries-get-build-path def distutils_dir_name(dname): """Returns the name of a distutils build directory""" f = "{dirname}.{platform}-{version[0]}.{version[1]}" return f.format(dirname=dname,platform=sysconfig.get_platform(),version=sys.version_info) def sakura_files( ): return [ 'sakura-source/src/baseline.cc', 'sakura-source/src/bit_operation.cc', 'sakura-source/src/bool_filter_collection.cc', 'sakura-source/src/concurrent.cc', 'sakura-source/src/convolution.cc', 'sakura-source/src/fft.cc', 'sakura-source/src/gen_util.cc', 'sakura-source/src/gridding.cc', 'sakura-source/src/interpolation.cc', 'sakura-source/src/mask_edge.cc', 'sakura-source/src/normalization.cc', 'sakura-source/src/numeric_operation.cc', 'sakura-source/src/statistics.cc' ] def source_files(path,root_filter=[ ],path_filter=[ ],subdir_filter=['tests','test','apps','demo'],file_filter=[ ],file_suffix_filter=""): """ find all of the source files to compile beneath path """ result = [ ] for root, dirs, files in os.walk(path): if root in root_filter or any(map(lambda x: root.endswith(x),a_priori_directory_exclusions)): continue subdir = os.path.basename(root) if subdir in subdir_filter or any(map(lambda x: (os.sep + x + os.sep) in root,subdir_filter)): continue path = root.split(os.sep) for file in files: if any(map(lambda x: x in root+os.sep+file, path_filter)): continue if file.endswith(file_suffix_filter) and not any(map(lambda s: (root + os.sep + file).endswith(s),file_filter)) and not file in a_priori_exclusions and not file in boost_exclusions: result.append(root + os.sep + file) return result ### ### see Roberto's comment in: ### https://stackoverflow.com/questions/3595363/properties-file-in-python-similar-to-java-properties ### def load_properties(filepath, sep='=', comment_char='#'): """ Read the file passed as parameter as a properties file. """ props = {} with open(filepath, "rt") as f: for line in f: l = line.strip() if l and not l.startswith(comment_char): key_value = l.split(sep) key = key_value[0].strip() value = sep.join(key_value[1:]).strip().strip('"') props[key] = value.split(' ') if key.startswith('build.flags') else value return props def so_version( ): delta=int(time.time()-1385614800) z=delta & 0xff y=(delta>>8)&0xff x=(delta>>16)&0xffff return "%d.%d.%d" % (x,y,z) def install_xml_casa( ): script = os.path.join('scripts','xml-casa') jar = os.path.join('scripts','java',xml_jar_file) bindir = os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__', "bin") javadir = os.path.join(bindir,'java') mkpath(javadir) copy2(script,bindir) copy2(jar,javadir) def generate_grpc(protos): protoc = os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__', "bin", "protoc") grpc_plugin = os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__', "bin", "grpc_cpp_plugin") assert os.path.exists(grpc_plugin), 'gRPC plugin not found' outdir=os.path.join('build', distutils_dir_name('binding'),'grpc') mkpath(outdir) for p in protos: assert os.path.isfile(p), "could not find gRPC proto '%s'" % p print('generating protocol for %s...' % os.path.basename(p)) genprotocol = [protoc, '-I%s' % os.path.dirname(p), '--cpp_out=%s' % outdir, p] genrpc = [protoc, '-I%s' % os.path.dirname(p), '--grpc_out=%s' % outdir, '--plugin=protoc-gen-grpc=%s' % grpc_plugin, p] print("\t%s" % " ".join(genprotocol)) run_process( genprotocol, err='could not generate protobuf bindings for %s' % p ) print("\t%s" % " ".join(genrpc)) run_process( genrpc, err='could not generate protobuf bindings for %s' % p ) return outdir def xml2cpp_proxy(input,output): """Convert dbus-cpp XML interface definition to a header file for the proxy object """ out_root="libcasatools/generated/include/casadbus" in_root="casa-source/code/casadbus" subdir=os.path.dirname(output) mkpath("%s%s%s" % (out_root,os.sep,subdir)) if Proc([ props['build.compiler.dbuscpp'], "%s%s%s" % (in_root,os.sep,input), \ "--proxy=%s%s%s" % (out_root,os.sep,output) ]) != 0: sys.exit('dbus proxy generation of %s%s%s failed' % (out_root,os.sep,output)) def generate_pyinit(moduledir,tools): """Generate __init__.py for the module """ outfile = os.path.join(moduledir,'__init__.py') with open(outfile, "w") as fd: fd.write("""###########################################################################\n""") fd.write("""########################## generated by setup.py ##########################\n""") fd.write("""###########################################################################\n""") fd.write("from __future__ import absolute_import\n") fd.write("__name__ = '%s'\n" % module_name) fd.write("__all__ = [ \"ctsys\",\n") for tool in tools: if tool != "utils": fd.write(" '%s',\n" % tool) fd.write(" ]\n") for tool in tools: if tool != "utils": fd.write("from .%s import %s\n" % (tool,tool)) config='''\ import casatools.ctuser as __user from .utils import utils as __utils import os as __os def __find_data_path( ): def find_mount_point(path): path = __os.path.abspath(path) while not __os.path.ismount(path): path = __os.path.dirname(path) return path #potential_data_paths = ['/opt/casa/data', '/home/casa/data/master', '/home/casa/data', '/export/data_1/casa/data'] potential_data_paths = [ ] casadata = [ d for d in (__os.environ['CASADATA'].split(':') if 'CASADATA' in __os.environ else [ ]) if __os.path.isdir(d) ] potential = [ d for d in potential_data_paths if __os.path.isdir(d) ] potential_local = [ d for d in potential if find_mount_point(d) == '/' ] potential_remote = [ d for d in potential if find_mount_point(d) != '/' ] used = set( ) return [ x for x in casadata + potential_local + potential_remote if x not in used and (used.add(x) or True)] def __find_user_data_path( ): def is_iter_container(v): try: _iter = iter(v) return not isinstance(v,str) except TypeError: return False if hasattr(__user,'datapath') and is_iter_container(__user.datapath): return list(filter(__os.path.isdir, map(__os.path.expanduser,__user.datapath))) else: return [ ] sakura( ).initialize_sakura( ) ## sakura requires explicit initialization ctsys = __utils( ) ctsys.initialize( __find_user_data_path( ) + [__os.path.dirname(__os.path.abspath(__file__)) + __os.sep + '__data__'] + __find_data_path( )) from .coercetype import coerce as __coerce __coerce.set_ctsys(ctsys) ## used to locate files from a partial path import atexit as __atexit __atexit.register(ctsys.shutdown) ## c++ shutdown ''' fd.write(dedent(config)) def generate_config(moduledir,propdict): """Generate config.py """ outfile = os.path.join(moduledir,"config.py") with open(outfile, "w") as fd: fd.write("""########################################################################### ########################## generated by setup.py ########################## ########################################################################### ### ### see Roberto's comment in: ### https://stackoverflow.com/questions/3595363/properties-file-in-python-similar-to-java-properties ### import os as __os def __load_properties(filepath, sep='=', comment_char='#'): props = {} with open(filepath, "rt") as f: for line in f: l = line.strip() if l and not l.startswith(comment_char): key_value = l.split(sep) key = key_value[0].strip() value = sep.join(key_value[1:]).strip().strip('"') props[key] = value.split(' ') if key.startswith('build.flags') else value return props build = __load_properties(__os.path.join(__os.path.dirname(__file__),'build.properties')) build['build.compiler.xml-casa'] = __os.path.join(__os.path.dirname(__os.path.abspath(__file__)),'__casac__','bin','xml-casa') """) def generate_lex(sources,output_dir='libcasatools/generated/include'): """Generate lex compilation files... """ for file in sources: name = os.path.basename(file) base = os.path.splitext(name)[0] if Proc([props['build.compiler.flex'], "-P%s" % base, "-o", "%s%s%s.lcc" % (output_dir,os.sep,base), file]) != 0: sys.exit('lex generation of %s%s%s.lcc failed' % (output_dir,os.sep,base)) def generate_yacc(sources,output_dir='libcasatools/generated/include'): """Generate yacc compilation files... """ for file in sources: name = os.path.basename(file) base = os.path.splitext(name)[0] if Proc([props['build.compiler.bison'], "-y", "-p", base, "-o", "%s%s%s.ycc" % (output_dir,os.sep,base), file]) != 0: sys.exit('lex generation of %s%s%s.ycc failed' % (output_dir,os.sep,base)) def generate_binding(sources,swig_dir='binding/generated/tools', header_dir='binding/generated/tools',source_dir='binding/generated/tools', tool_dir=''): """Generate swig binding code from CASA XML files... """ xml_casa = props['build.compiler.xml_casa'] assert os.path.isfile(xml_casa) and os.access(xml_casa,os.X_OK), "casa xml generation script not found..." proc = Popen([xml_casa, '-all', '-output-tool-subdir','output-i=%s' % swig_dir, 'output-h=%s' % header_dir, 'output-c=%s' % source_dir, 'output-tool=%s' % tool_dir ] + sources, stdout=PIPE, stderr=PIPE) out,err = pipe_decode(proc.communicate( )) if proc.returncode != 0: print(err) sys.exit('casa xml generation failed') print(out) lines = out.split('\n') needed = [ tool.strip( ) for line in lines for tool in line[5:].split(',') if line.startswith('') ] tool_lines = [ line[5:].strip( ) for line in lines if line.startswith('') and ':' in line[5:] ] lib_lines = [ line[5:].strip( ) for line in lines if line.startswith('') and '<' in line[5:] ] libs = { } for l in lib_lines: x = [i.strip( ) for i in l.split('<')] if len(x) != 2: sys.exit( "error in library target: %s" % l ) libs[x[0]] = [ t.strip( ) for t in x[1].split( ) ] tools = { } for l in tool_lines: x = [i.strip( ) for i in l.split(':')] if len(x) != 2: sys.exit( "error in tool target: %s" % l ) tools[x[0]] = [ t.strip( ) for t in x[1].split( ) ] ## needed - tools that are used (returned, accepted as parameters, etc.) by other tools ## libs - libraries to be created for building the tools (i.e. shared tool object modules) ## tools - all tools along with what they need to be built against return (needed,libs,tools) def run_process( cmd, err, dir=".", stdin=None, env=None ): sys.stdout.flush( ) proc = Popen( cmd, cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=None if env is None else dict(os.environ,**env) ) if stdin is None else Popen( cmd, cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=stdin, env=None if env is None else dict(os.environ, **env) ) out,err = pipe_decode(proc.communicate( )) exit_code = proc.wait( ) if proc.returncode != 0: print("failure...") print(err) sys.stdout.flush( ) sys.exit(err) print(out) return proc.returncode def write_wrapper( dir, ccache, compiler ): ccache_wrapper='''#!/usr/bin/perl #open(LOG,">> /tmp/wrapper-log-file.txt"); #print LOG '%s', ' ', join(' ',@ARGV), "\\n"; #close(LOG); exec { '%s' } '%s', '%s', @ARGV; ''' ### ### when the user uses /usr/lib64/ccache/gcc et al. writing any ### wrappers results in an infinite loop... ### if len(ccache) > 0: with open(join(dir,os.path.basename(compiler)), "w") as f: f.write(ccache_wrapper % (compiler,ccache,ccache,compiler)) os.chmod(join(dir,os.path.basename(compiler)), 0o0755) ###################################################################################################### ## gRPC depends on a few other packages, some of which use libtool and automake. The problem ## with automake and libtool is that they were designed as if there is only one way to build ## and link libraries and applications. They permit not configuration, they ignore compiler ## specifications. It is just a inflexible and brittle system. To ensure that ccache is used ## by these extra packages, we create a wrapper library and add it to the beginning of our ## PATH. (BTW, gRPC's makefile is very nice) ###################################################################################################### broken_autoconf_compiler_dir=os.path.realpath(join('build',distutils_dir_name('compilers'))) def create_ccache_bin( ): """gRPC and protobuf don't seem to honor CC and CXX """ mkpath(broken_autoconf_compiler_dir) for c in [props['build.compiler.cc'], props['build.compiler.cxx']]: if not os.path.exists(join(broken_autoconf_compiler_dir,os.path.basename(c))): write_wrapper( broken_autoconf_compiler_dir, props['build.compiler.ccache'], c ) def build_grpc( prefix, srcdir, collectdir ): """Build grpc (https://github.com/grpc/grpc/blob/master/): (1) do a straight build of grpc to get the C/C++ libraries and protoc compiler (2) rebuild protobuf to install and then cherry pick the include files """ extra_env = { 'PATH': "%s:%s" % (broken_autoconf_compiler_dir, os.environ['PATH']), 'CC': os.path.basename(props['build.compiler.cc']), 'CXX': os.path.basename(props['build.compiler.cxx']) } if os.path.isdir("grpc-source"): if not os.path.isdir(srcdir): print("copying the source directory...") run_process( ["rsync","-aq","grpc-source/",srcdir], err='could not copy the grpc source tree' ) #### need to set @rpath/ prefix for install name... makefile = "%s/Makefile" % srcdir if os.path.isfile(makefile): with open(makefile) as fd: s = fd.read() s = s.replace('-install_name ', '-install_name $(RPATH_DIR)') with open(makefile, "w") as fd: fd.write(s) mkpath(prefix) create_ccache_bin( ) if os.path.isdir(prefix): if not os.path.exists("grpc-source/third_party/protobuf/LICENSE"): print("checking out google protobuf...") run_process( ["git", "submodule", "update", "--init", "--recursive", "grpc-source"], err='git protobuf checkout failed' ) srcdir_arg = os.path.realpath(srcdir) prefix_arg = os.path.realpath(prefix) collectdir_arg = os.path.realpath(collectdir) mkpath(collectdir_arg) print("building google grpc...") run_process( ["make", "RPATH_DIR=@rpath/", "prefix=%s" % prefix_arg, "PROTOBUF_CONFIG_OPTS=--prefix=%s" % collectdir_arg, "VERBOSE=1", "install"], err='build of grpc failed', dir=srcdir_arg, env=extra_env ) print("installing google protobuf...") run_process( ["make", "install"], err='building google protobuf failed', dir="%s/third_party/protobuf" % srcdir_arg, env=extra_env ) print("copying the protobuf includes...") run_process( ["rsync","-aq","%s/include/" % collectdir_arg,"%s/include" % prefix], err='could not copy the protobuf include tree' ) print("copying the protobuf libs...") run_process( ["rsync","-aq","%s/lib/" % collectdir_arg,"%s/lib" % prefix], err='could not copy the protobuf lib tree' ) print("copying the protobuf compiler...") run_process( ["rsync","-aq","%s/bin/" % collectdir_arg,"%s/bin" % prefix], err='could not copy the protobuf bin tree' ) ## ## grpc "make install" seems to generate a symlink from '...so.5' instead of '...so.1' ## libdir = join(prefix,"lib") if os.path.exists(join(libdir,"libgrpc++.so.1.8.7")) and os.path.exists(join(libdir,"libgrpc++.so.5")): os.rename(join(libdir,"libgrpc++.so.5"),join(libdir,"libgrpc++.so.1")) if os.path.exists(join(libdir,"libgrpc++_unsecure.so.1.8.7")) and os.path.exists(join(libdir,"libgrpc++_unsecure.so.5")): os.rename(join(libdir,"libgrpc++_unsecure.so.5"),join(libdir,"libgrpc++_unsecure.so.1")) ## remove 'libtool' droppings for root,subdirs,files in os.walk(prefix): for f in files: p = join(root,f) if not islink(p) and p.endswith(".la"): os.remove(p) ## on linux grpc's "make install" seems to create a 'libgrpc++.so.5' symlink to 'libgrpc++.so.1.8.5' ## instead of a 'libgrpc++.so.1' symlink def build_protobuf( prefix, srcdir, collectdir ): """Build grpc (https://github.com/grpc/grpc/blob/master/): (1) do a straight build of grpc to get the C/C++ libraries and protoc compiler (2) rebuild protobuf to install and then cherry pick the include files """ if os.path.isdir("grpc-source"): if not os.path.isdir(srcdir): print("copying the source directory...") run_process( ["rsync","-aq","grpc-source/third_party/protobuf/",srcdir], err='could not copy the protobuf source tree' ) ## here we would really like to patch protobuf's Makefile.am to create libraries as we would like right off the ## bat (e.g. "-install_name @rpath/libprotobuf.14.dylib"), but 'libtool' is a britte cludge mkpath(prefix) create_ccache_bin( ) if os.path.isdir(prefix): srcdir_arg = os.path.realpath(srcdir) prefix_arg = os.path.realpath(prefix) collectdir_arg = os.path.realpath(collectdir) mkpath(collectdir_arg) extra_env = { 'PATH': "%s:%s" % (broken_autoconf_compiler_dir, os.environ['PATH']), 'CC': os.path.basename(props['build.compiler.cc']), 'CXX': os.path.basename(props['build.compiler.cxx']) } print("autogen for google protobuf...") run_process( ["autoreconf","-f", "-i", "-Wall,no-obsolete"], err='autogen of protobuf failed', dir=srcdir_arg, env=extra_env ) print("configuring google protobuf...") run_process( ["./configure", "--prefix=%s" % prefix_arg], err='build of grpc failed', dir=srcdir_arg, env=extra_env ) print("compiling google protobuf...") run_process( ["make"], err='building google protobuf failed', dir=srcdir_arg, env=extra_env ) found=[ ] searchdir=join(srcdir_arg,"src",".libs") for f in listdir(searchdir): if f.startswith("libprotobuf") and islib(f): file = join(searchdir,f) found.append(file) if len(found) < 4: sys.exit("build of dynamic protobuf libraries failed") tgtdir = "%s/lib" % prefix_arg for f in found: fname = os.path.basename(f) if islink(f): if not os.path.exists(join(tgtdir,fname)): linkto = os.readlink(f) os.symlink(linkto,join(tgtdir,fname)) elif isfile(f): copy2(f,tgtdir) if sys.platform == 'darwin': run_process( ["install_name_tool", "-id", "@rpath/%s" % fname, join(tgtdir,fname) ], err='could not update install_name for %s' % fname ) def tool_files(tool): src = ['binding/tools/%s/%s' % (tool,f) for f in listdir('binding/tools/%s' % tool) if f.endswith(".cc")] src += ['binding/generated/tools/%s/%s' % (tool,f) for f in listdir('binding/generated/tools/%s' % tool) if f.endswith(".cc")] src += ['binding/generated/tools/%s/%s' % (tool,f) for f in listdir('binding/generated/tools/%s' % tool) if f.endswith(".i")] inc = [ ] incs = ['binding/generated/tools/%s/%s' % (tool,f) for f in listdir('binding/generated/tools/%s' % tool) if f.endswith(".h")] if len(incs) > 0: inc.append('binding/generated/tools/%s' % tool) incs = ['binding/tools/%s/%s' % (tool,f) for f in listdir('binding/tools/%s' % tool) if f.endswith(".h")] if len(incs) > 0: inc.append('binding/tools/%s' % tool) return (inc,src) platform_cflags = { 'darwin': [ ], 'linux2': [ '-fcx-fortran-rules' ], 'linux': [ '-fcx-fortran-rules' ], ##### ##### these cause a segmentation violation in test_setjy ##### # 'linux2': [ '-fopenmp', '-fcx-fortran-rules' ], # 'linux': [ '-fopenmp', '-fcx-fortran-rules' ], }; props = load_properties('build.properties') module_cflags = { '/casacore/': ['-DCFITSIO_VERSION_MAJOR=3', '-DCFITSIO_VERSION_MINOR=370', '-DCASA_BUILD=1'\ '-DHAVE_FFTW3', '-DHAVE_FFTW3_THREADS', '-DHAVE_READLINE', \ '-DUSE_THREADS', '-DUseCasacoreNamespace', '-DWCSLIB_VERSION_MAJOR=5', \ '-DWCSLIB_VERSION_MINOR=15', '-fsigned-char', '-DWITHOUT_BOOST', '-DCASATOOLS' ] + platform_cflags[sys.platform], '/code/': ['-DAIPS_64B', '-DAIPS_AUTO_STL', '-DAIPS_DEBUG', \ '-DAIPS_HAS_QWT', '-DAIPS_LINUX', '-DAIPS_LITTLE_ENDIAN', \ '-DAIPS_STDLIB', '-DCASACORE_NEEDS_RETHROW', '-DCASA_USECASAPATH', \ '-DDBUS_CPP', '-DQWT6', '-DUseCasacoreNamespace', \ '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE', '-DNO_CRASH_REPORTER', \ '-fno-omit-frame-pointer', '-DWITHOUT_ACS', '-DWITHOUT_BOOST', \ '-DCASATOOLS' ] + [ '-DWITHOUT_DBUS' ] if props['option.dbus'] == "0" else [ ] \ + platform_cflags[sys.platform], 'binding/': ['-DAIPS_64B', '-DAIPS_AUTO_STL', '-DAIPS_DEBUG', '-DAIPS_HAS_QWT', \ '-DAIPS_LINUX', '-DAIPS_LITTLE_ENDIAN', '-DAIPS_STDLIB', \ '-DCASACORE_NEEDS_RETHROW', '-DCASA_USECASAPATH', '-DDBUS_CPP', '-DQWT6', \ '-DUseCasacoreNamespace', '-D_FILE_OFFSET_BITS=64', '-D_LARGEFILE_SOURCE', \ '-DNO_CRASH_REPORTER', '-fno-omit-frame-pointer', '-DWITHOUT_ACS', '-DWITHOUT_BOOST', \ '-DCASATOOLS' ] + [ '-DWITHOUT_DBUS' ] if props['option.dbus'] == "0" else [ ] + platform_cflags[sys.platform] } def customize_compiler(self): """inject customization into distutils. Getting distutils to use a specfic compiler with a fully-quaified path and specfic flags is difficult. By default, it seems to just use 'gcc', i.e. whichever compiler happens to be in the user's path. I want to select a specific compiler using autoconf. I found this reference useful: https://github.com/rmcgibbo/npcuda-example/blob/master/cython/setup.py """ # make it swallow fortran files.... self.src_extensions.extend( [".f",".f90"] ) # save references to the default compiler_so and _comple methods default_compiler_so = self.compiler_so default_linker_so = self.linker_so supercc = self._compile superld = self.link ccache = [ props['build.compiler.ccache'] ] if 'build.compiler.ccache' in props and len(props['build.compiler.ccache']) > 0 else [ ] cflags = map(lambda pair: pair[1],filter(lambda pair: pair[0].startswith('build.flags.compile') and "boost" not in pair[0],props.items())) cflags = [item for sublist in cflags for item in sublist] ### python has not yet hit upon a flatten function... if 'build.python.numpy_dir' in props and len(props['build.python.numpy_dir']) > 0: cflags.insert(0,'-I' + props['build.python.numpy_dir']) ### OS could have different version of python in ### /usr/include (e.g. rhel6) new_compiler_cxx = ccache + [props['build.compiler.cxx'], '-g', '-std=c++11','-Ibinding/include','-Ibinding/generated/include','-Ilibcasatools/generated/include','-Icasa-source/code','-Icasa-source','-Icasa-source/casacore', '-Iinclude', '-Isakura-source/src'] + cflags + default_compiler_so[1:] new_compiler_cc = ccache + [props['build.compiler.cc'], '-g', '-Ibinding/include','-Ibinding/generated/include','-Ilibcasatools/generated/include','-Icasa-source/code','-Icasa-source','-Icasa-source/casacore', '-Iinclude', 'sakura-source/src'] + cflags + default_compiler_so[1:] new_compiler_fortran = [props['build.compiler.fortran']] new_compiler_cxx = list(filter(lambda flag: not flag.startswith('-O'),new_compiler_cxx)) new_compiler_ccc = list(filter(lambda flag: not flag.startswith('-O'),new_compiler_cc)) local_path_file = ".lib-path.%d" % sys.hexversion local_mangle_file = ".lib-mangle.%d" % sys.hexversion if os.path.isfile(local_path_file): with open(local_path_file,'rb') as f: local_library_path = pickle.load(f) else: local_library_path = [ ] if os.path.isfile(local_mangle_file): with open(local_mangle_file,'rb') as f: library_mangle = pickle.load(f) else: library_mangle = { } def _link(target_desc, objects, output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None): fn = os.path.basename(output_filename) if fn.startswith('lib') and fn.endswith(".so"): print("linking shared library...") self.linker_so = list(map(lambda f: "-dynamiclib" if f == "-bundle" else f,self.linker_so)) if sys.platform == 'darwin': if output_filename.endswith(".so"): output_filename = output_filename[:-3] + ".dylib" subname = os.path.basename(output_filename) extra_postargs=list(map( lambda arg: arg % subname if '%s' in arg else arg, extra_postargs )) dir = os.path.dirname(output_filename) target_desc=CCompiler.SHARED_LIBRARY if dir not in local_library_path: local_library_path.insert(0,dir) with open(local_path_file,'wb') as f: pickle.dump(local_library_path,f) bfn = (fn[3:])[:-3] library_mangle[bfn.split('.')[0]] = bfn with open(local_mangle_file,'wb') as f: pickle.dump(library_mangle,f) superld(target_desc, objects, output_filename, output_dir, [library_mangle[l] if l in library_mangle else l for l in libraries], library_dirs+local_library_path, runtime_library_dirs, export_symbols, debug, extra_preargs, extra_postargs, build_temp, target_lang) self.linker_so = default_linker_so # now redefine the _compile method. This gets executed for each # object but distutils doesn't have the ability to change compilers # based on source extension: we add it. def _compile(obj, src, ext, cc_args, postargs, pp_opts): if ext == ".f" or ext == ".f90" : print("fortran compile...") arch = platform.architecture()[0].lower() if sys.platform == 'darwin' or sys.platform.startswith('linux'): compiler_so = new_compiler_fortran if (ext == ".f90"): cc_args = ["-O3", "-fPIC", "-c", "-ffree-form", "-ffree-line-length-none"] if (ext == ".f"): cc_args = ["-O3", "-fPIC", "-c", "-fno-automatic", "-ffixed-line-length-none"] # Force architecture of shared library. if arch == "32bit": cc_args.append("-m32") elif arch == "64bit": cc_args.append("-m64") else: print("\nPlatform has architecture '%s' which is unknown to " "the setup script. Proceed with caution\n" % arch) try: self.spawn(compiler_so + cc_args + [src, '-o', obj] + postargs) except DistutilsExecError as msg: raise CompileError(msg) else: if ext == ".c" : print("c compile...") new_compiler = new_compiler_cc else: print("c++ compile...") new_compiler = new_compiler_cxx ## get the cflags for the module being built; key is a subdir, value are flags m_cflags = map(lambda x: x[1] if x[0] in src else [], module_cflags.items()) m_cflags = [item for sublist in m_cflags for item in sublist] ### python has not yet hit upon a flatten function... self.set_executable('compiler_so', clean_args(new_compiler + m_cflags + ( [ '-DUSE_GRPC' ] if props['option.grpc'] != "0" else [ ] ))) supercc(obj, src, ext, clean_args(cc_args), clean_args(postargs), clean_args(pp_opts)) # reset the default compiler_so (may not be necessary) self.compiler_so = default_compiler_so # inject our redefined _compile method into the class self._compile = _compile self.link = _link def customize_swig(self): swig_exe = props['build.compiler.swig'] if len(props['build.compiler.swig']) > 0 else "swig" self.swig = swig_exe # run the customize_compiler class casa_build_ext(build_ext): def build_extensions(self): customize_compiler(self.compiler) customize_swig(self) build_ext.build_extensions(self) class casa_build(Command): user_options = [ # The format is (long option, short option, description). ] def initialize_options(self): pass def finalize_options(self): pass def run(self): global a_priori_directory_exclusions global a_priori_exclusions moduledir = os.path.join('build', distutils_dir_name('lib'), module_name) cerberusdir = os.path.join(moduledir, '__cerberus__') casacdir = os.path.join(moduledir, '__casac__') libdir = os.path.join(casacdir, 'lib') mkpath(moduledir) copy_tree("src/python",moduledir) copy2('build.properties',moduledir) generate_config(moduledir,props) if os.path.exists(cerberusdir): remove_tree(cerberusdir) copy_tree("cerberus/cerberus",cerberusdir) for root, dirs, files in os.walk(cerberusdir): for file in files: if file.endswith('.py'): fpath = os.path.join(root, file) print("\tfixing %s" % fpath) with io.open(fpath,'r',encoding='utf8',newline='\n') as fd: s = fd.read() s = s.replace("from cerberus", "from casatools.__cerberus__") with io.open(fpath,'w',encoding='utf8',newline='\n') as fd: fd.write(s) TOOL_XML = source_files("xml/tools",file_suffix_filter=".xml") tools = [ os.path.splitext(os.path.basename(f))[0] for f in TOOL_XML ] generate_pyinit(moduledir,tools) if props['option.dbus'] != "0": xml2cpp_proxy('xml/PlotServerProxy.interface.xml', 'plotserver/PlotServerProxy.proxy.h') xml2cpp_proxy('xml/DBusSession.interface.xml', 'session/DBusSession.proxy.h') xml2cpp_proxy('xml/ViewerProxy.interface.xml', 'viewer/ViewerProxy.proxy.h') else: a_priori_directory_exclusions += [ 'casadbus/session', 'casadbus/plotserver', 'casadbus/synthesis', 'casadbus/utilities', 'casadbus/viewer' ] a_priori_exclusions += [ 'FlagAgentDisplay.cc', 'DistributedSynthesisIterBot.cc', 'DistSIIterBot.cc', 'InteractiveMasking.cc', 'SynthesisIterBot.cc' ] CASACORE_YACC = source_files("casa-source/casacore",file_suffix_filter=".yy") CODE_YACC = source_files("casa-source/code",file_suffix_filter=".yy",subdir_filter=['tests','test','apps','display','plotms','guitools','display3d','demo','casaqt','Filling']) CASACORE_LEX = source_files("casa-source/casacore",file_suffix_filter=".ll") CODE_LEX = source_files("casa-source/code",file_suffix_filter=".ll",subdir_filter=['tests','test','apps','display','plotms','guitools','display3d','demo','casaqt','Filling']) generate_lex(CASACORE_LEX + CODE_LEX) generate_yacc(CASACORE_YACC + CODE_YACC) (NEEDED,LIBS,TOOLS) = generate_binding(TOOL_XML,tool_dir=os.path.join('build', distutils_dir_name('lib'), module_name)) if props['option.grpc'] != "0": # hopefully this will repace dbus build_grpc( os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__'), os.path.join('build', distutils_dir_name('grpc')), os.path.join('build', distutils_dir_name('grpc-install')) ) build_protobuf( os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__'), os.path.join('build', distutils_dir_name('protobuf')), os.path.join('build', distutils_dir_name('grpc-install')) ) grpc_srcdir = generate_grpc( [ os.path.join('casa-source','code','casatools','protos','registrar.proto') ] ) else: grpc_srcdir = "" print("copying xml-casa...") install_xml_casa( ) CORE_SRC = source_files("casa-source/casacore",file_suffix_filter=".cc") MIR_SRC = source_files("casa-source/casacore/mirlib",file_suffix_filter=".c") SAKURA_SRC = sakura_files( ) CORE_F77 = source_files("casa-source/casacore",file_suffix_filter=".f", #file_filter=['fgridsd.f'] ) grpc_incdir = os.path.join('build', distutils_dir_name('lib'), module_name, '__casac__', 'include') GRPC_SRC = ['%s/%s' % (grpc_srcdir,f) for f in listdir(grpc_srcdir) if f.endswith(".cc")] if len(grpc_srcdir) != 0 else [ ] BINDING_SRC = ['binding/source/%s' % f for f in listdir('binding/source') if f.endswith(".cc")] + GRPC_SRC CODE_SRC = source_files("casa-source/code",file_suffix_filter=".cc",subdir_filter=['tests','test','apps','display','plotms','guitools','display3d','demo','casaqt','convert','Filling','ImagerObjects2'],file_filter=['MeasurementComponents/rGridFT.cc'], path_filter=['MeasurementComponents/WOnlyConvFunc.cc','TransformMachines2/EVLAConvFunc.cc']) CODE_ATM = source_files("casa-source/code/atmosphere/ATM",file_suffix_filter=".cpp") #CODE_F77 = source_files("casa-source/code/synthesis/fortran",file_suffix_filter=".f",file_filter=['fgridsdclip.f']) CODE_F77 = source_files("casa-source/code/synthesis/fortran",file_suffix_filter=".f", #file_filter=['fgridsdclip.f'] ) ### from macports it is called libdbus-cpp.dylib, from CASA's RPM it is called libcasa-dbus-cpp.so... if props['option.dbus'] == "0": dbuslibs = [ ] else: dbuscpp = props['build.name.lib.dbuscpp'] if 'build.name.lib.dbuscpp' in props and len(props['build.name.lib.dbuscpp']) > 0 else 'casa-dbus-cpp' dbuslibs = [ dbuscpp, 'dbus-1' ] prop_linking = list(filter(lambda x: len(x) > 0,list(chain.from_iterable(map(lambda pair: pair[1],filter(lambda pair: pair[0].startswith('build.flags.link'),props.items())))))) ldflags = list(filter(lambda x: not x.startswith('-l'),prop_linking)) prop_libs = list(map(lambda x: x[2:],list(filter(lambda x: x.startswith('-l'),prop_linking)))) if sys.platform == 'darwin': ### need to get '/opt/local/lib/gcc5' from gfortran directly rpath = [ '-install_name', '@rpath/%s', '-Wl,-rpath,@loader_path' ] archflags = ['-L/opt/local/lib/gcc5'] archlibs = [ ] else: rpath = [ '-Wl,-rpath,' + ":".join(['$ORIGIN/lib'] + list(map(lambda s: s[2:],filter(lambda s: s.startswith('-L'),ldflags)))) ] archflags = [ ] archlibs = ['gomp'] grpc_libs = [ 'grpc++','grpc','gpr','protobuf' ] if props['option.grpc'] != "0" else [ ] ext = [ Extension( module_name + ".__casac__.lib.lib" + module_name, language='c++', sources=BINDING_SRC + CODE_SRC + CORE_SRC + MIR_SRC + SAKURA_SRC + CODE_ATM + CODE_F77 + CORE_F77, include_dirs=['binding',grpc_srcdir,grpc_incdir], extra_link_args=ldflags+rpath+archflags, libraries=prop_libs + dbuslibs + ['sqlite3','xslt','xml2','xerces-c','fftw3f_threads','fftw3f','fftw3_threads','fftw3','lapack','wcs','cfitsio','rpfits','blas'] + grpc_libs + ['readline','gfortran','dl'] + archlibs ) ] swig_opt = [ '-outdir', casacdir, '-c++', '-threads', "-Ibinding/include" ] if pyversion >= 3: print('generating python3 bindings...') swig_opt.insert(0,"-py3") incdirs = { } libsrc = { } for t in TOOLS: (I,L) = tool_files(t) incdirs[t] = I libsrc[t] = L for lb in LIBS: incdirs[lb] = [ i for t in LIBS[lb] for i in incdirs[t] ] libsrc[lb] = [ l for t in LIBS[lb] for l in libsrc[t] ] for lb in LIBS: if sys.platform == 'darwin': rpath = [ '-install_name', '@rpath/%s', '-Wl,-rpath,@loader_path' ] ext.append(Extension( module_name + ".__casac__.lib.%s" % lb, language='c++', sources=libsrc[lb], include_dirs=['binding'] + incdirs[lb], extra_link_args=ldflags + ['-L'+libdir] + rpath + archflags, swig_opts=swig_opt, libraries=[module_name] + prop_libs + dbuslibs + ['sqlite3','xslt','xml2','xerces-c','fftw3f_threads','fftw3f','fftw3_threads','fftw3','lapack','wcs','cfitsio','rpfits','blas','blas'] + grpc_libs + ['readline','gfortran','dl'] + archlibs )) for t in TOOLS: inc = [ ]; lib = [ ]; src = [ ] for dep in TOOLS[t]: inc += incdirs[dep] if dep.startswith('lib'): lib += [ dep[3:] ] else: src += libsrc[dep] if sys.platform == 'darwin': rpath = [ '-Wl,-rpath,@loader_path/lib','-Wl,-rpath,@loader_path' ] ext.append(Extension( module_name + ".__casac__._%s" % t, language='c++', sources=src, include_dirs=['binding'] + inc, extra_link_args=ldflags + ['-L'+libdir] + rpath + archflags, swig_opts=swig_opt, libraries=[module_name] + prop_libs + dbuslibs + ['sqlite3','xslt','xml2','xerces-c','fftw3f_threads','fftw3f','fftw3_threads','fftw3','lapack','wcs','cfitsio','rpfits','blas','blas'] + grpc_libs + ['readline','gfortran','dl'] + lib + archlibs)) setup( name="casa",version="5.5.0-36", maintainer="Darrell Schiebel", maintainer_email="drs@nrao.edu", author="CASA development team", author_email="aips2-request@nrao.edu", url="http://casa.nrao.edu", download_url="https://casa.nrao.edu/download/", license="GNU Library or Lesser General Public License (LGPL)", platforms=["MacOS X"], description = __doc__.split("\n")[0], long_description="\n".join(__doc__.split("\n")[2:]), classifiers=filter(None, classifiers.split("\n")), package_dir={'casa':'lib'}, packages=['casa'], cmdclass={ 'build_ext': casa_build_ext, 'test': casa_test }, ext_modules=ext ) ### ### this generates the __init__.py for the __casac__ submodule... ### imports = "\n".join([ "from %s.__casac__.%s import %s" % (module_name,t,t) for t in TOOLS ]) alllist = ",\n ".join([ "'%s'" % t for t in TOOLS ]) with open(os.path.join(casacdir,'__init__.py'),"w") as fd: fd.write("from __future__ import absolute_import\n") fd.write("__name__ = '__casac__'\n") fd.write("__all__ = [ %s ]\n\n" % alllist) fd.write("%s\n" % imports) try: spawn(["rsync", "-avz", "rsync://casa-rsync.nrao.edu/casa-data", "%s/__data__" % moduledir]) except: print("RSYNC OF CASA DATA FROM 'rsync://casa-rsync.nrao.edu/casa-data' FAILED!") class casa_test(Command): user_options = [ # The format is (long option, short option, description). ('output-regression', None, 'run the output (i.e. generated files) regression comparison'), ] def initialize_options(self): self.__test_dir = "build/%s" % distutils_dir_name('testing') self.__lib_dir = os.path.abspath("build/%s" % distutils_dir_name('lib')) self.__env = os.environ.copy( ) if 'PYTHONPATH' in self.__env: self.__env['PYTHONPATH'] = ("%s:%s" % (self.__env['PYTHONPATH'],self.__lib_dir)) else: self.__env['PYTHONPATH'] = self.__lib_dir self.__regression_dir = "build/%s" % distutils_dir_name('regression') #self.__regression_ref_dir = "tests/output-regression/reference-%d.%d" % (sys.version_info[0],sys.version_info[1]) self.__regression_ref_dir = "tests/output-regression/reference" self.__regression_sample_gen = "scripts/output-snapshot" self.__regression_sample_dir = "%s/%s" % (self.__regression_dir,"output") self.output_regression = 0 def finalize_options(self): pass def __dump_output(self, working_dir, bname, out, err): stdout_path = "%s/%s-stdout.txt" % (working_dir,bname) stdout_fd = open(stdout_path, 'w') stdout_fd.write(out) stdout_fd.close( ) stderr_path = "%s/%s-stderr.txt" % (working_dir,bname) stderr_fd = open(stderr_path, 'w') stderr_fd.write(err) stderr_fd.close( ) return (stdout_path,stderr_path) def __run_test(self,tabwidth,test_path,working_dir): label = '.'.join(os.path.basename(test_path).split('.')[:-1]) sys.stdout.write(label + '.' * (tabwidth - len(label))) sys.stdout.flush( ) proc = Popen( [sys.executable,test_path], cwd=working_dir, env=self.__env, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) (output, error) = pipe_decode(proc.communicate( )) exit_code = proc.wait( ) (stdout_path,stderr_path) = self.__dump_output(working_dir,"log",output,error) print(" ok" if exit_code == 0 else " fail") return (exit_code, label, stdout_path, stderr_path) def __generate_sample(self): if os.path.exists(self.__regression_dir): remove_tree(self.__regression_dir) mkpath(self.__regression_sample_dir) proc = Popen( [self.__regression_sample_gen,"out=%s" % self.__regression_sample_dir], env=self.__env, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) (output, error) = pipe_decode(proc.communicate( )) exit_code = proc.wait( ) self.__dump_output(self.__regression_dir,"sample-generation",output,error) return exit_code def __compare_reg(self, tabwidth, label, refpath, samplepath): sys.stdout.write(label + '.' * (tabwidth - len(label))) sys.stdout.flush( ) proc = Popen( ["/usr/bin/diff",refpath,samplepath], env=self.__env, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) (output, error) = pipe_decode(proc.communicate( )) exit_code = proc.wait( ) print(" ok" if exit_code == 0 else " fail") (op,ep) = self.__dump_output(os.path.dirname(samplepath),label,output,error) return (exit_code, label, op, ep) def __collect_tests(self, testdir): tests = [ ] for dir, subdirs, files in os.walk(testdir): for f in files: if f.endswith(".py") and f.startswith("test_"): workingdir = "%s/%s" % (self.__test_dir,f[:-3]) mkpath(workingdir) tests.append((os.path.abspath("%s/%s" % (dir,f)),workingdir)) return tests def __collect_regression_files(self, regdir): regression = { } for dir, subdirs, files in os.walk(regdir): for f in files: if f != "log.txt": regression[f] = "%s/%s" % (dir,f) return regression def __collect_regression(self): regression_ref = { } regression_sample = { } if os.path.isdir(self.__regression_ref_dir): if isexe(self.__regression_sample_gen): if self.__generate_sample( ) == 0: regression_ref = self.__collect_regression_files(self.__regression_ref_dir) regression_sample = self.__collect_regression_files(self.__regression_sample_dir) else: print("warning, generation of regression sample failed; skipping regression test") else: print( "warning, regression sample generator (%s) does not exist; skipping regression test" % self.__regression_sample_gen) else: print("warning, regression reference (%s) does not exist; skipping regression test" % self.__regression_ref_dir) return (regression_ref, regression_sample) def run(self): if os.path.exists(self.__test_dir): remove_tree(self.__test_dir) mkpath(self.__test_dir) tests = self.__collect_tests("tests/tools") (regression_ref, regression_sample) = self.__collect_regression( ) testwidth = 0 if len(tests) == 0 else max(map(lambda x: len(os.path.basename(x[0]))+3,tests)) regressionwidth = 0 if len(regression_ref) == 0 else max(map(lambda x: len(x)+3,regression_ref.keys( ))) tabwidth = max(testwidth,regressionwidth,45) start_time = time.time() testresults = list(map(lambda params: self.__run_test(tabwidth,*params),tests)) len_message = "regression file count" print( len_message + '.' * (tabwidth - len(len_message)) + (" ok" if len(regression_ref) == len(regression_sample) else " fail") ) regressionresults = [] if self.output_regression: regression_keys = filter(lambda k: k in regression_sample, regression_ref.keys( )) regressionresults = list(map(lambda k: self.__compare_reg(tabwidth,k,regression_ref[k],regression_sample[k]), regression_keys)) end_time = time.time() results = testresults + regressionresults print('-' * (tabwidth + 8)) passed = list(filter(lambda v: v[0] == 0,results)) failed = list(filter(lambda v: v[0] != 0,results)) print("ran %s tests in %.02f minutes, %d passed, %d failed" % (len(results),(end_time-start_time) / 60.0,len(passed),len(failed))) print("OK" if len(failed) == 0 else "FAIL") sys.exit(0 if len(failed) == 0 else 1) if __name__ == '__main__': ## ensure that we use the version of python selected by configure... targetexecutable=pipe_decode(subprocess.check_output(["/opt/rh/rh-python36/root/usr/bin/python", "-c", "import sys; print(sys.executable)"])).split('\n')[0] if sys.executable != targetexecutable: if not os.path.exists('.restarted'): open('.restarted','w').close() os.execvp( '/opt/rh/rh-python36/root/usr/bin/python', ['/opt/rh/rh-python36/root/usr/bin/python'] + sys.argv ) else: print("cannot configure with /opt/rh/rh-python36/root/usr/bin/python") sys.stdout.flush( ) os._exit(1) if os.path.exists('.restarted'): os.remove('.restarted') if not os.path.isfile('build.properties'): sys.exit('Run configure to create build properties, then try again...') if 'build.compiler.cxx' not in props: sys.exit('Configuration error, not compiler found... try again...') setup( name="casa",version="5.5.0-36", maintainer="Darrell Schiebel", maintainer_email="drs@nrao.edu", author="CASA development team", author_email="aips2-request@nrao.edu", url="http://casa.nrao.edu", download_url="https://casa.nrao.edu/download/", license="GNU Library or Lesser General Public License (LGPL)", platforms=["MacOS X"], description = __doc__.split("\n")[0], long_description="\n".join(__doc__.split("\n")[2:]), classifiers=filter(None, classifiers.split("\n")), package_dir={'casa':'lib'}, packages=['casa'], cmdclass={ 'build': casa_build, 'test': casa_test }, ext_modules=[ ] )