ant-ivy-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Shawn Castrianni <Shawn.Castria...@halliburton.com>
Subject RE: Ivy for C/C++ libraries
Date Tue, 12 Apr 2011 16:53:53 GMT
There is nothing special about the ivy files from the standard documentation except that I
introduced some custom XML properties to help me with the artifact pattern.

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
xmlns:ext="http://ant.apache.org/ivy/extra">
        <info organisation="Company" module="testModule">
                <repository name="Subversion" url="${env.SVN_URL_REVISION}"/>
                <description>This module contains the test module.</description>
        </info>
        <configurations>
                <conf name="all"/>
                <conf name="win32"/>
                <conf name="win64"/>
                <conf name="linux32"/>
                <conf name="linux64"/>
                <conf name="solaris"/>
        </configurations>
        <publications>
                <artifact name="com_company_test_module" type="jar" ext="jar" ext:path=""/>
                <artifact name="include" type="include" ext="zip" ext:path=""/>
                <artifact name=" com_company_test_module " ext="dll" type="bin" ext:path="win32"
conf="all,win32"/>
                <artifact name=" com_company_test_module " ext="dll" type="bin" ext:path="win64"
conf="all,win64"/>
                <artifact name=" com_company_test_module " ext="so" type="bin" ext:path="linux32"
conf="all,linux32"/>
                <artifact name=" com_company_test_module " ext="so" type="bin" ext:path="linux64"
conf="all,linux64"/>
                <artifact name=" com_company_test_module " ext="so" type="bin" ext:path="solaris"
conf="all,solaris"/>
        </publications>
                <dependencies>
                        <dependency name="depModule" rev="latest.testing" conf="*->@"/>
                </dependencies>

</ivy-module>


Below is my post processing ant code that scans dependencies directory looking for include.zip
files and unzipping them, or symbolic links to be made, or execute bits to be set.  All of
this is keyed off of custom IVY XML properties which make this stuff pretty easy.  I don't
have time to clean up this code to make it easier for you, so good luck sorting through it.


   <target name="dependencies.process" depends="init.ivy">
      <!--Perform post dependency processing-->
      <condition property="isUnix">
         <isfalse value="${isWindows}"/>
      </condition>
      <ac:for param="dependencyDir">
         <dirset dir="${env.DEPENDENCIES_DIR}">
            <include name="*"/>
         </dirset>
         <sequential>
            <ac:var name="dependencyName" unset="true"/>
            <basename file="@{dependencyDir}" property="dependencyName"/>
            <!--Check for dependency subsetting and remove those artifacts that do not
belong-->
            <!--Search for any symbolic links that need to be made-->
            <ac:var name="dependencySubsets" unset="true"/>
            <ac:if>
               <isset property="${dependencyName}.subsets"/>
               <ac:then>
                  <ac:propertycopy property="dependencySubsets" from="${dependencyName}.subsets"/>
                  <echo message=":: Keeping only subsets: ${dependencySubsets} from module:
${dependencyName}"/>
               </ac:then>
            </ac:if>
            <ac:if>
               <available file="@{dependencyDir}/ivy/ivy.xml"/>
               <ac:then>
                  <xt:xmltask source="@{dependencyDir}/ivy/ivy.xml" failWithoutMatch="false">
                     <xt:call path="ivy-module/publications/artifact">
                        <param name="artifactName" path="@name"/>
                        <param name="artifactExt" path="@ext"/>
                        <param name="artifactType" path="@type"/>
                        <param name="artifactPath" path="@ext:path"/>
                        <param name="artifactAliases" path="@ext:aliases" default=""/>
 <!--Custom IVY XML property to show symbolic links to be made-->
                        <param name="artifactZip" path="@ext:zip" default="false"/>
 <!--Custom IVY XML property to show files that need unzipping-->
                        <param name="artifactExecutable" path="@ext:executable" default="false"/>
 <!--Custom IVY XML property to show a file that needs execute bit set on unix-->
                        <xt:actions>
                                 <ac:if>
                                    <isfalse value="${dependencies.skipSymbolicLinks}"/>
                                    <ac:then>
                                       <!--Process symbolic links-->
                                       <ac:for param="artifactAlias" list="@{artifactAliases}">
                                          <sequential>
                                              <ac:if>
                                             <and>
                                                 <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}"
type="dir"/>
                                                 <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"
type="file"/>
                                                 <not>
                                                <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactAlias}"
type="file"/>
                                                 </not>
                                             </and>
                                             <ac:then>
                                                 <echo message="Creating symbolic link:
@{artifactAlias}->@{artifactName}.@{artifactExt}"/>
                                                 <ac:if>
                                                    <istrue value="${isWindows}"/>
                                                    <ac:then>
                                                       <copy file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"
tofile="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactAlias}"/>
                                                    </ac:then>
                                                    <ac:else>
                                                       <se:smartexec executable="ln" dir="${basedir}"
failonerror="true" showCommand="false" ignorePrepend="true" if="isUnix">
                                                         <arg value="-s"/>
                                                         <arg value="@{artifactName}.@{artifactExt}"/>
                                                         <arg value="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactAlias}"/>
                                                       </se:smartexec>
                                                    </ac:else>
                                                 </ac:if>
                                             </ac:then>
                                             <ac:elseif>
                                                <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactAlias}"
type="file"/>
                                                <ac:then>
                                                    <echo message="Symbolic link already
exists: @{artifactAlias}->@{artifactName}.@{artifactExt}"/>
                                                </ac:then>
                                             </ac:elseif>
                                              </ac:if>
                                          </sequential>
                                       </ac:for>
                                    </ac:then>
                                 </ac:if>
                                 <!--Process zips that should be extracted-->
                                 <ac:if>
                                    <and>
                                       <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                       <or>
                                          <istrue value="@{artifactZip}"/>
                                          <and>
                                             <equals arg1="@{artifactType}" arg2="include"/>
                                             <matches string="@{artifactName}" pattern="include.*"/>
                                             <equals arg1="@{artifactExt}" arg2="zip"/>
                                          </and>
                                       </or>
                                    </and>
                                    <ac:then>
                                       <unzip src="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"
dest="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}"/>
                                       <delete file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                       <!--Process zip executables that should be set-->
                                       <ac:if>
                                          <istrue value="@{artifactExecutable}"/>
                                          <ac:then>
                                             <echo message="Setting executable bit on contents
of zip: @{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                             <se:smartexec executable="chmod" dir="${basedir}"
failonerror="true" showCommand="false" ignorePrepend="true" if="isUnix">
                                                <arg value="-R"/>
                                                <arg value="a+x"/>
                                                <arg value="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}"/>
                                             </se:smartexec>
                                          </ac:then>
                                       </ac:if>
                                    </ac:then>
                                 </ac:if>
                                 <!--Process executables that should be set-->
                                 <ac:if>
                                    <and>
                                       <available file="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                       <istrue value="@{artifactExecutable}"/>
                                    </and>
                                    <ac:then>
                                       <echo message="Setting executable bit: @{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                       <se:smartexec executable="chmod" dir="${basedir}"
failonerror="true" showCommand="false" ignorePrepend="true" if="isUnix">
                                          <arg value="a+x"/>
                                          <arg value="@{dependencyDir}/@{artifactType}/@{artifactHome}/@{artifactHomeType}/@{artifactPath}/@{artifactName}.@{artifactExt}"/>
                                       </se:smartexec>
                                    </ac:then>
                                 </ac:if>
                        </xt:actions>
                     </xt:call>
                  </xt:xmltask>
               </ac:then>
            </ac:if>
         </sequential>
      </ac:for>
   </target>


How I build my classpath:

   <target name="module.classPath" depends="module.jarPath,module.eclipseClassPath,dependencies.check">
      <mkdir dir="${env.DEPENDENCIES_DIR}"/>
      <mkdir dir="${env.BUILD_DIR}/classes"/>
      <path id="moduleClassPath">
         <pathelement location="${env.BUILD_DIR}/classes"/>
         <path refid="moduleJarPath"/>
         <path refid="moduleEclipseClassPath"/>
         <fileset dir="${env.DEPENDENCIES_DIR}">
            <include name="**/jar/*.jar"/>
         </fileset>
      </path>
      <!--Make available as a property as well-->
      <pathconvert property="moduleClassPath" refid="moduleClassPath"/>
      <ac:if>
         <istrue value="${verbose}"/>
         <ac:then>
            <echo message="moduleClassPath=${moduleClassPath}"/>
         </ac:then>
      </ac:if>
   </target>



How I set my INCLUDE_DIR and BINARY_DIR env variables to pass to visual studio and stuff:

   <target name="dependencies.check" depends="init.ivy">
      <mkdir dir="${env.DEPENDENCIES_DIR}"/>
      <!--Set env properties based on where dependency module artifacts exist-->
      <ac:for param="dependencyDir">
         <dirset dir="${env.DEPENDENCIES_DIR}">
            <include name="*"/>
         </dirset>
         <sequential>
            <ac:var name="dependencyName" unset="true"/>
            <basename file="@{dependencyDir}" property="dependencyName"/>
            <at:stringutil property="dependencyNameUpper" string="${dependencyName}">
               <at:uppercase/>
            </at:stringutil>
            <property name="env.${dependencyNameUpper}_INCLUDE_DIR" value="@{dependencyDir}${file.separator}include"/>
            <property name="env.${dependencyNameUpper}_PLATFORM_INCLUDE_DIR" value="@{dependencyDir}${file.separator}include${file.separator}${os.platform}"/>
            <property name="env.${dependencyNameUpper}_BINARY_DIR" value="@{dependencyDir}${file.separator}bin${file.separator}${os.platform}"/>
         </sequential>
      </ac:for>
      <ac:if>
         <istrue value="${verbose}"/>
         <ac:then>
            <echoproperties regex="env\..*_INCLUDE_DIR"/>
            <echoproperties regex="env\..*_BINARY_DIR"/>
         </ac:then>
      </ac:if>
   </target>



How I pass these env variables to my launch of visual studio and stuff  (smartexec is the
same as exec but I enhanced it a bit, you can probably use regular exec here):

      <macrodef name="launchNative" description="Runs an arbitrary command with full runtime
environment">
         <attribute name="executable"/>
         <attribute name="spawn" default="true"/>
         <attribute name="returnCodeProperty" default=""/>
         <element name="arguments" optional="true" implicit="true"/>
         <sequential>
             <se:smartexec executable="@{executable}" dir="${basedir}" spawn="@{spawn}"
ignorePrepend="true" showCommand="false" failonerror="false" resultproperty="@{returnCodeProperty}">
               <arguments/>
               <env key="DEPENDENCIES_DIR" value="${env.DEPENDENCIES_DIR}"/>
               <envset>
                  <propertyref regex="env\..*_INCLUDE_DIR"/>
                  <mapper type="regexp" from="env\.(.*_INCLUDE_DIR)" to="\1"/>
               </envset>
               <envset>
                  <propertyref regex="env\..*_BINARY_DIR"/>
                  <mapper type="regexp" from="env\.(.*_BINARY_DIR)" to="\1"/>
               </envset>
               <env key="BUILD_DIR" value="${env.BUILD_DIR}"/>
               <env key="${runtimeLibPathVar}" path="${runtimeLibPath}"/>
            </se:smartexec>
         </sequential>
      </macrodef>
---
Shawn Castrianni

-----Original Message-----
From: Scott Palmer [mailto:swpalmer@gmail.com]
Sent: Monday, April 11, 2011 3:01 PM
To: ivy-user@ant.apache.org
Subject: Re: Ivy for C/C++ libraries

Excellent!  This gives me some confidence that this will work for me. Since it has been done
before, hopefully won't have to fight too hard to get this working.

Do you have any sample ivy files you could share that would nudge me in the right direction?
 Last time I checked I couldn't find any examples on the Ivy site or via google that did this
sort of thing.  Just the first couple steps would be helpful.

I have very little experience with Ivy.. basically only for simple Java projects and Ivy +
Ant (+the IvyBeans NetBeans plugin) magically do what I want.  Things end up on my classpath
and I don't know exactly how that happens.  Something as as simple as the right way to do
the post-processing Ant task to unzip header files and how you set your <module>_INCLUDE_DIR
would be helpful.  I've already got Ant calling out to Visual Studio - it a matter of getting
the build environment configured with all the dependencies that I'm working out at this point.

Thanks,

Scott

On 2011-04-11, at 3:00 PM, Shawn Castrianni wrote:

> I have posted several messages to this user group concerning this topic.  Here is a short
summary of what I have done:
>
> 1. Use IVY configurations to separate out the different artifacts for
> the different platforms 2. I zip up the header files and run a
> post-processing ant task to unzip them after the IVY resolve and
> retrieve are complete 3. I leave the dll's and so's as separate
> artifacts specifying their correct configuration so that when downloading artifacts on
win32, only win32 artifacts are retrieved 4. I set ant properties called <module>_INCLUDE_DIR
and <module>_BINARY_DIR that point to the include and "bin/<platform>" subdirectories
so that include paths and library paths can be set more easily 5. I build everything in ANT
which either call visual studio devenv command line utility to build from the vcproj files
on windows  OR  do one of three things on unix platforms.
>       a. use exec to call the compiler commands directly
>       b. use exec to call legacy build scripts like make
>       c. use cpptasks
>
> It all works very well.
>
> ---
> Shawn Castrianni
>
>
> -----Original Message-----
> From: Scott Palmer [mailto:swpalmer@gmail.com]
> Sent: Monday, April 11, 2011 1:44 PM
> To: ivy-user@ant.apache.org
> Subject: Ivy for C/C++ libraries
>
> I want to use Ivy to manage some projects that use both Java and C+_+.  For the C++ side
we have several 3rd-party SDKs that we need to use.  These basically contain header files
(.h) and lilbraries for linking (.lib) and DLL files needed to deploy.
>
> I was thinking of storing the 3rd-party SDKs as ZIPs and have some automated process
to un-zip them to a known location e.g.  %SDKS%\module_name\* so the C++ code could find them.
 But if it is easier to deal with the individual files as assets then I could do that as well.
>
> Is there any sort of sample or tutorial that would help cover this case?
> It seems the examples are very java-centric, I am likely not going to be using Ant when
building the native parts of the project, so I would like to call Ivy directly.. but I'm not
against making an Ant wrapper that invokes the native build process as well.
>
> Regards,
>
> Scott
>
> ----------------------------------------------------------------------
> This e-mail, including any attached files, may contain confidential and privileged information
for the sole use of the intended recipient.  Any review, use, distribution, or disclosure
by others is strictly prohibited.  If you are not the intended recipient (or authorized to
receive information for the intended recipient), please contact the sender by reply e-mail
and delete all copies of this message.


Mime
View raw message