Как мы делали сборки

    Введение


    Когда проект разрастается, обзаводится множеством модулей и зависимостей, настройка сборки проекта вручную может занять непомерно много времени. К тому же настройкой, а значит и тратой времени, занимаются все технические участники проекта от разработчиков, тестировщиков, до администраторов.

    К тому же надо постоянно обновлять разработческие и тестовые системы, да еще и ничего не перепутать. Тут не обойтись без практики непрерывной интеграции.


    В этой статье приведен опыт внедрения сборок с помощью maven, поэтому базовые знания по maven необходимы. Для быстрого старта будет достаточно изучения сайта http://www.apache-maven.ru, для более детального освоения темы — стоит обратиться к первоисточнику http://maven.apache.org

    Цель статьи не научить пользоваться майвеном, а показать опыт внедрения с положительными и отрицательными решениями. Обладая этими знаниями, гораздо проще и быстрее внедрить сборки maven у себя в команде.

    Почему не ant?


    Предупреждая подобного рода вопросы, скажу, что мы используем и ant, но не для самой сборки, а для технических функций, об этом ниже.

    Еще важным преимуществом maven является возможность собирать только тот код, с которым ты работаешь, все остальное собирается по ночам на отдельном сервере.

    Окружение


    Сначала стоит рассказать о структуре наших проектов и подходах к разработке. Это очень важно, в силу того, что проект развивается уже много лет и имеет структуру, не соответствующую maven-webapp-artifact

    И так, у нас имеется множество модулей, хранящихся в одном SVN репозитарии. Каждый модуль имеет основную ветку разработки (trunk), а также метки (tags) и ветки (branches) по необходимости. Большинство модулей содержат как java-классы, так и jsp-страницы, скрипты, графику и пр. Большинство модулей являются самостоятельными веб-приложениями и могут работать независимо. Примеры модулей: core, soap, workflow, addons, common… Их я насчитал порядка 100.

    Проект чаще всего состоит из отдельного модуля, в котором размещаются специфические ресурсы и логика в java-классах. Иногда, такого модуля нет. Итоговая сборка проекта состоит из набора модулей в виде одного web-приложения.

    Необходимые модулю библиотеки хранятся в папке lib прямо в репозитарии, для веб-ресурсов имеется своя папка sx-war. А также стандартные папки src и test.



    Естественно, почти все модули зависят от core, и друг от друга, по необходимости.

    Еще есть база данных с мета-информацией. На основе нее взаимодействуют модули, строится вся работа с пользователем. Например, блок публикации — тоже является единицей мета-информации и хранится в БД. То есть помимо самих данных, в базе хранятся настройки работы с этими данными. Они настраиваются в консоли, которая тоже построена на блоках публикации. Есть возможность переносить мета-информацию с помощью пакетов обновлений.

    В идеале, каждый модуль имеет свой общий пакет с мета-информацией. БД для core самая легкая БД и может расширяться любым модулем. Ядро — почти application-server, только без возможности динамической загрузки\выгрузки многофункциональных модулей. Не все модули имеют отделенную мету, но мы к этому стремимся :)

    До нашей эры


    Ходит у нас такая фраза. Означает, что «это» было очень давно, еще до начала нашей работы в компании. Расскажу, как проходила настройка сборки до меня. Мне тоже пришлось потратить немало времени на настройку в первый раз.

    И вот вы устроились к нам на работу. Идет второй день. Первый ушел на просмотр скринкастов по подсистемам и тренировки работы с мета-информацией. Надо настроить сборку. Хорошо, если в базе знаний по проекту есть информация по необходимым модулям для проекта. Часто эта информация не актуальна (забывают обновлять или обновляют от случая к случаю). Информации о зависимостях самих модулей не найти, а та что есть, тоже устаревает.

    Из SVN извлекаются trunk-версии всех необходимых модулей, создается проект в IDE. А дальше самое сложное: настроить импорт всех необходимых библиотек и связи модулей. Все еще осложняется, когда надо исключать одни версии библиотек из одних модулей и использовать другие. Настроить сборку всех модулей в одну папку. Далее настроить сервер веб-приложений (используется tomcat).

    И вот проект настроен, затем надо настроить второй, третий, версию первого (использовать branches для работы над ошибками). Разработчику становится не по себе.

    Поменялись зависимости, сломались сборки у всех. А администраторы используют ant для создания production-сборок — у них тоже все ломается. Часто возникают проблемы из-за разных сборок у администратора и разработчика.

    Первая попытка


    У нас не было специальных людей, отвечающих за сборку, как не было и хороших знаний maven. Поэтому первая попытка внедрения maven на проектах провалилась.

    Родительский pom.xml был помещен в отдельную папку репозитария. После чего в отдельной проектной папке настраивались svn-externals и включались все необходимые проекту модули, плюс родительский pom.xml в отдельной папке:



    Классический подход с использованием иерархии модулей в единой структуре SVN нам не подошел, потому что каждый модуль используется в десятках проектов. А не только в одном единственном. А любые манипуляции с parent pom на проектах нежелательны. К тому же фиксация версии любого модуля автоматически отразится на всех проектах.

    Все необходимые библиотеки не искались на http://search.maven.org, потому что их очень много и все они обезличены в репозитарии (в папке lib хранятся библиотеки без версий. Например axis.jar, jtds.jar, velocity.jar). Поступили просто: все библиотеки с помощью скрипта загрузили в Nexus. GroupId и ArtifactId были заданы по маске sx.<имя библиотеки> (sx.axis).

    Вот как выглядел типичный pom.xml модуля:

    Базовый pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    	<!-- Родительский проект -->
    	<parent>
    		<groupId>sx.config</groupId>
    		<artifactId>project-settings</artifactId>
    		<version>2.0.1</version>
    		<relativePath>project-settings/pom.xml</relativePath>
    	</parent>
    	<!-- Координаты -->
    	<groupId>sx.builds</groupId>
    	<artifactId>wfBuilder</artifactId>
    	<version>2.0.1</version>
    	<packaging>pom</packaging>	
    	<!-- Репозиторий плагинов -->
    	<pluginRepositories>
    		<pluginRepository>
    			<id>sx-repository</id>
    			<url>http://v5-neptun/nexus/content/repositories/sx-repository</url>
    		</pluginRepository>
    	</pluginRepositories>
    	<!-- Репозиторий Зависимостей -->
    	<repositories>
    		<repository>
    			<id>sx-repository</id>
    			<url>http://v5-neptun/nexus/content/repositories/sx-repository</url>
    		</repository>
    	</repositories>
    	<!--URL SVN-->
    	<scm>
    		<connection>scm:svn:svn://svn-server/buildsMaven/trunk/workflowBuild</connection>		
    	</scm>	
    	<!--Модули-->		
    	<modules>		
    		<module>core</module>
    		<module>workflow</module>
    	</modules>		
    </project>
    


    Видно, что необходимо менять в нем список модулей для каждого проекта.

    Во время сборки, каждый модуль собирался в отдельный war, а потом распаковывался в общий деплой с помощью maven-overlay.

    Причины провала

    Полностью перечеркнул преимущества maven подход использования svn-externals. Это свойство не позволяет однозначно зафиксировать код всех модулей без правки свойств svn папки вручную. Это становится практически нереально при наличии 10-15 модулей и выпуске патча для некой версии. А так хотелось использовать maven release plugin.

    Плюсы

    • Все собирается «здесь и сейчас». Разработчик не зависит от периода обновления SNAPSHOT-зависимостей (сборки из основной ветки разработки);
    • Разработчик может вносить изменения сразу в несколько модулей (сомнительный пункт, потому что нарушается инкапсуляция модулей);
    • Виден весь набор необходимых модулей;


    Минусы

    • Полная сборка всех модулей — длительная процедура;
    • Нельзя нормально зафиксировать версию кода;
    • Все библиотеки не берутся из публичного репозитория, добавление же новой — это отдельная процедура;
    • Возможен jar-hell, когда кто то решит использовать библиотеку из публичного репозитория и она уже имеется в корпоративном (в деплой попадут обе версии, а то и три!). Это происходит, потому что изменяется GroupId:ArtifactId:Version;
    • Код вроде бы хранится в одной папке SVN, а вычекивать надо совсем другую (с svn-externals). Не прозрачно — для эстетов;


    Вторая попытка


    Вторая попытка внедрения сборок развивалась в несколько итераций.

    Итерация 1

    В первую очередь необходимо было получить механизм фиксации кода (выпуска версии) как отдельных модулей, так и всего продукта в целом. Для этого мы избавились от использования svn-externals. Каждый модуль получился автономным и собирался отдельно. В конечную сборку попадали все зависимости, которые есть у модуля.

    Также был модифицирован родительский pom.xml в соответствии с задачами. Все модули используют его в качестве базового:

    Новый базовый pom.xml
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <!-- Координаты -->
      <groupId>sx.config</groupId>
      <artifactId>main-settings</artifactId>
      <version>1.1-SNAPSHOT</version>
      <packaging>pom</packaging>
    
      <!--URL SVN-->
      <scm>
        <connection>scm:svn:svn://svn-server/maven/main-settings/trunk</connection>
      </scm>
    
      <!-- Репозиторий плагинов -->
      <pluginRepositories>
        <pluginRepository>
          <id>sx-repository</id>
          <url>http://v5-neptun/nexus/content/repositories/sx-repository</url>
        </pluginRepository>
      </pluginRepositories>
    
      <!-- Репозиторий Зависимостей -->
      <repositories>
        <repository>
          <id>sx-repository</id>
          <url>http://v5-neptun/nexus/content/repositories/sx-repository</url>
        </repository>
        <repository>
          <id>releases-repository</id>
          <url>http://v5-neptun/nexus/content/repositories/releases</url>
        </repository>
        <repository>
          <id>snapshots-repository</id>
          <url>http://v5-neptun/nexus/content/repositories/snapshots</url>
        </repository>
        <repository>
          <id>central-repository</id>
          <url>http://v5-neptun/nexus/content/repositories/central</url>
        </repository>
      </repositories>
      <profiles>
        <profile>
          <id>production</id>
          <!-- На ФТП публикуются только конечные сборки продуктов. Модули публиковать не нужно -->
          <distributionManagement>
            <repository>
              <id>ftp-repository</id>
              <url>ftp://ftp.sample.com/builds</url>
            </repository>
          </distributionManagement>
        </profile>
    
        <profile>
          <id>development</id>
          <activation>
            <activeByDefault>true</activeByDefault>
          </activation>
          <!-- Этот репозиторий указывается только для дочерних модулей -->
          <distributionManagement>
            <snapshotRepository>
              <id>snapshots-repository</id>
              <url>http://v5-neptun/nexus/content/repositories/snapshots</url>
            </snapshotRepository>
            <repository>
              <id>releases-repository</id>
              <url>http://v5-neptun/nexus/content/repositories/releases</url>
            </repository>
          </distributionManagement>
        </profile>
      </profiles>
    
      <!-- Настройки сборки -->
      <build>
        <defaultGoal>package</defaultGoal>
        <!--Исходный код -->
        <sourceDirectory>src</sourceDirectory>
        <testSourceDirectory>test</testSourceDirectory>
        <!--Ресурсы -->
        <resources>
          <resource>
            <directory>src</directory>
            <includes>
              <include>**/*.properties</include>
              <include>**/*.sql</include>
              <include>**/*.xml</include>
            </includes>
          </resource>
        </resources>
    
        <extensions>
          <!-- Enabling the use of FTP -->
          <extension>
            <groupId>org.apache.maven.wagon</groupId>
            <artifactId>wagon-ftp</artifactId>
            <version>1.0-beta-6</version>
          </extension>
        </extensions>
    
        <plugins>
          <!--Сборка -->
          <!--Синтаксический сахар для идеи -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.2</version>
            <configuration>
              <!-- У нас не стандартные директории -->
              <warSourceDirectory>sx-war</warSourceDirectory>
              <attachClasses>true</attachClasses>
            </configuration>
          </plugin>
    
          <!--Задаем опции выделения памяти, на больших модулях может выпадать out of memory-->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <configuration>
              <minmemory>256m</minmemory>
              <maxmemory>512m</maxmemory>
            </configuration>
          </plugin>
    
          <!-- Настройки Ресурсов -->
          <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
              <encoding>cp1251</encoding>
            </configuration>
          </plugin>
          <!-- Версия плагина для вычекивания -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-scm-plugin</artifactId>
            <version>1.4</version>
            <configuration>
              <username>${SvnUsername}</username>
              <password>${SvnPassword}</password>
            </configuration>
          </plugin>
          <!-- Плагин выпуска релизов модуля -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-release-plugin</artifactId>
            <configuration>
              <tagBase>svn://gelios/cms/maven/main-settings/tags</tagBase>
              <branchBase>svn://gelios/cms/maven/main-settings/branches</branchBase>
              <preparationGoals>clean install</preparationGoals>
              <goals>deploy</goals>
              <autoVersionSubmodules>true</autoVersionSubmodules>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    


    Итерация 2

    Во все модули проекта внедрили плагин выпуска версий. Для этого в каждый модуль были добавлены блоки:

    Подключение плагина выпуска релизов
     <!-- Путь до модуля в SVN. Меняется при выпуске версий автоматически -->
     <scm>
       <connection>scm:svn:svn://svnserver/module/trunk</connection>
     </scm>
    
     <build>
       <plugins>
         <!-- Плагин выпуска релизов модуля -->
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-release-plugin</artifactId>
           <configuration>
             <!-- Пути в SVN для хранения версий модуля -->
             <tagBase>svn://svnserver/module/tags</tagBase>
             <branchBase>svn://svnserver/module/branches</branchBase>
             <preparationGoals>clean install</preparationGoals>
             <goals>deploy</goals>
             <autoVersionSubmodules>true</autoVersionSubmodules>
           </configuration>
         </plugin>
         ...
       </plugins>
    


    Были мысли вынести эту конфигурацию в базовый pom.xml, и использовать свойство ArtifactId-Version, но не во всех проектах это значение совпадает с названием папки в репозитарии. Поэтому мысль была отложена до лучших времен. Первым версию получил как раз базовый для всех модулей pom.xml.

    В базовый pom.xml добавили новый профиль: production. Он закачивает сборку на корпоративный FTP и может дальше может распространяться на проекты.

    Итерация 3

    После неприятного столкновения с jar-hell, решено было привести библиотеки в порядок во всех сборках. А это было не просто, потому что только в ядре оказалось больше 100 библиотек и почти все без версий. Каждую надо было найти в публичном репозитарии, “вычислить” версию. Вскрылись библиотеки “сюрпризы” с внутренними сборками и патчами, измененными версиями. Их мы бережно поместили в maven-репозиторий с сохранением координат артифакта, но с припиской _custom в Version.

    В качестве репозитория у нас используется Nexus. На нем был настроен шлюз к публичным репозиториям с кешированием. Появилась единая точка входа: корпоративный maven-репозиторий. До этого их было больше трех: библиотеки, релизы, ежедневные сборки и остальные публичные репозитории. Все требовали авторизацию. Три похожих репозитория в каждом pom.xml, да еще параметры доступа в settings.xml вызывали постоянную путаницу.

    Делали попытку оставить ссылку на репозиторий только в базовом pom.xml. Это вполне реально, но при первой сборке любого модуля майвен должен загрузить базовый модуль из репозитория, а его координаты неизвестны. Можно это сделать вручную, после этого все отлично работает. Отказались из-за непрозрачности этого действия.

    Итерация 4

    Настроили еженощные сборки всех базовых и проектных модулей в системе непрерывной интеграции Hudson. С ними не возникло проблем, потому что модули теперь полностью независимы. Нет никакой разницы, публичная это библиотека или проектный модуль. Сборки на основе maven запускаются после каждого изменения кода в SVN и успешные артифакты попадают в репозитарий Nexus.

    Со временем, настроили каскадную сборку модулей в задачах, а также деплой на разработческие сборки и сборки для тестирования. Деплой выполняется с помощью достаточно простых ant-скриптов. Они извлекают из Nexus последнюю сборку модуля (dependency:get), распаковывают ее на сервере и перезапускают сервер приложений (сами скрипты можно найти в конце статьи).

    Плюсы

    • Можно работать с каждым модулем в отдельности;
    • Фиксируя версии всех модулей-зависимостей можно зафиксировать весь код проекта;
    • Непрерывная интеграция избавляет от рутинной работы и позволяет быстрее переносить функционал в продуктивную среду и к заказчику;
    • Выпуск версии модуля полностью контролируем и достаточно прост;
    • Появилась возможность вести разработку только с одним конкретным модулем. Ведь общий деплой нескольких модулей может влиять на конечное поведение кода;
    • Благодаря Hudson, всегда видно, кто сломал сборку;
    • Вообще не надо настраивать проекты, IDE все сама делает. Надо только запустить сборку (да и mvn package достаточно);
    • Всегда ясно, от какого кода зависит модуль. А раньше всегда собирался trunk со своими ошибками, битыми коммитами и пр.;


    Минусы

    • В IDE нет общего проекта со всеми модулями, поэтому внесение изменений сразу в несколько модулей требует отдельной работы с каждым модулем. Это конечно не особо удобно, но концептуально правильно, потому что любой модуль должен быть самодостаточен;
    • Нельзя выпустить все версии компонентов каскадно, при выпуске основного продукта


    Развиваем решение


    В процессе работы, в сборки вносятся правки. Для тех, кто все еще собирает «по-старинке» заведена страница в базе знаний, которая содержит зависимости модулей. Эта информация обновляется на основе pom.xml модуля каждую ночь отдельной задачей в Hudson (не забываем о DRY).

    Для ускорения сборки модулей была исключена лишняя работа во время сборки. Например, мы собираем модуль soap, который зависит от core. Код core попадает в конечную сборку soap. Далее собирается project, который зависит от core и soap. soap в отдельности не используется, поэтому из его сборки исключается core, а в project он включается. Тем самым мы ускоряем сборку. Для возможности сборки soap с включением зависимого core был добавлен профиль сontext, который запускается при необходимости.

    Можно заметить, что все модули встречаются в pom.xml дважды: одна запись используется при компиляции, вторая означает, что модуль попадает в деплой. Чтобы не подменять версии модулей по всему pom.xml, все версии корпоративных модулей были вынесены в отдельные свойства и располагаются в самом начале файла. Это снижает вероятность ошибки при переходе на другую версию:

    Использование свойств для хранения версий
    <!-- Версии компонент и другие свойства.
         В самом начале, чтобы проще искать -->
     <properties>
       <sx.core>4.5-SNAPSHOT</sx.core>
     </properties>
     ...
     <profiles>
       <profile>
         <!--Профиль сборки контекста-->
         <id>context</id>
         <dependencies>
           <dependency>
             <groupId>sx.core</groupId>
             <artifactId>core</artifactId>
             <version>${sx.core}</version>
             <type>war</type>
             <!-- Модуль попадет в деплой через maven-overlay -->
             <scope>runtime</scope>
           </dependency>
         </dependencies>
       </profile>
     </profiles>
    
     <!-- Настройка зависимостей -->
     <dependencies>
       <dependency>
         <groupId>sx.core</groupId>
         <artifactId>core</artifactId>
         <version>${sx.core.core}</version>
         <classifier>classes</classifier>
         <!-- Модуль используется только для сборки\компиляции -->
         <scope>provided</scope>
       </dependency>
       ...
     </dependencies>
    



    ant-cкрипты для работы с maven-артифактами

    Заключение


    Так была внедрена непрерывная интеграция в нашем проекте. Пропала необходимость в ручных обновлениях кода на серверах. Всегда видны результаты сборки, которые рассылаются по RSS. Большой экран мониторинга сборки еще не поставили.

    Новые разработчики не тратят много времени на настройку сборок. А это только радует.

    Наладился выпуск версий кода, теперь этот процесс почти полностью автоматизирован и не занимает много времени. Стало гораздо легче сопровождать ранее выпущенные версии.

    Новые наработки попадают на контексты разработки в течение суток, а значит и к заказчику они попадают быстрее. Сложно уловимые ошибки интеграции тоже стали проявляться, а значит, и исправляться, быстрее.

    UPDATE: Полезная статья по опыту внедрения от комментирующих: http://bazhenov.me/blog/2011/04/09/build.html
    Share post

    Similar posts

    Comments 23

      0
      Однако с Maven не всё так радужно.

      Вы правильно указали на необходимость поддерживаться свой Nexus, т.к. внешние репозитории могут внезапно отваливаться или исчезать или исчезать интернет.

      Ещё для меня загадка как собрать и протестировать проект под разными JDK.

      Лютую ненависть вызывает этап генерации кода. Почему-то, все считают своим долгом что-нибудь, неважно что, на этом этапе сгенерировать.

      Вот с разрешением зависимостей Maven справляется отлично.

      Сейчас трогаю связку Ant+Ivy. Но пока приходится плясать с бубном.
        +1
        Все просто, подключаем плагин:
              <!-- Настройки компиляции -->
              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                  <encoding>cp1251</encoding>
                  <source_>${jdk.version}</source_>
                  <target>${jdk.version}</target>
                </configuration>
              </plugin>
        


        source_ — потому что парсер закрывает тег.

        и ставим jdk 1.5. Можно использовать properties-файл. К примеру. jdk я переключаю просто:

        1. Ставлю несколько jdk в разные папки: jdk_5, jdk_6 и пустую jdk
        2. Создаю два bat-файла с содержимым:
        rmdir jdk
        mklink /D jdk jdk_5
        и
        rmdir jdk
        mklink /D jdk jdk_6

        Можно переключаться. В linux еще проще. Одну проблему решить не смог с дефолтным jre, его файлы попадают в system32 и их никакими ссылками не заменить, да еще и в реестре прописывается. Думаю, тоже вопрос решаем.

        В заведении Nexus-a проблем нет, если проект достаточно велик.

        «Почему-то, все считают своим долгом...» — сборка зависит полностью от pom, так что надо один раз все настроить…
          0
          Ну это ж шевелиться надо, 2 кнопки нажимать. Или скрипт рядом ваять. Что ни говорите, а Ант универсальней.

          С другой стороны при разрастании проекта, Ант-скрипты становятся, мягко говоря, трудно сопровождаемыми.
            +1
            Мы в большинстве своем собираем под jdk 1.6, очень редко надо собирать под jdk 1.5, поэтому переключить jdk батником не составляет труда:

            0
            Для сборки под разные версии JDK можно использовать профили.
              0
              Ну их же надо переключать.

              Поясню. У меня есть библиотека, которая ант-скриптом собирается и тестируется под 2мя JDK, затем складывается в один архив с исходниками и документацией. Все это делается одной кнопкой.
                0
                Тестировать и собирать можно под разными jdk, в сборку же попадает сборка из одной jdk. Надо просто попробовать настроить для своих целей сборку. У нас не было такой необходимости.

                Тесты запускаются под разными JDK? Есть различия в поведении или просто проверяется возможность сборки под конкретной jdk?

                У нас есть модули, которые должны иметь возможность собираться под конкретной jdk, поэтому при сборке делается проверка такой возможности:

                 <!--Проверяем, что можно собрать модуль под определенной jdk-->
                      <plugin>
                        <groupId>org.jvnet</groupId>
                        <artifactId>animal-sniffer</artifactId>
                        <version>1.2</version>
                        <executions>
                          <execution>
                            <id>check-java-version</id>
                            <phase>compile</phase>
                            <goals>
                              <goal>check</goal>
                            </goals>
                            <configuration>
                              <signature>
                                <groupId>org.jvnet.animal-sniffer</groupId>
                                <artifactId>java1.5</artifactId>
                                <version>1.0</version>
                              </signature>
                            </configuration>
                          </execution>
                        </executions>
                      </plugin>
                
                  0
                  Можно указать список необходимых для активации профилей:

                  Details on profile activation

                  Profiles can be explicitly specified using the -P CLI option.

                  This option takes an argument that is a comma-delimited list of profile-ids to use. When this option is specified, no profiles other than those specified in the option argument will be activated.

                  mvn groupId:artifactId:goal -P profile-1,profile-2


                  Также можно задать профили через настройки Мавена в файле settings.xml
              0
              Мы в новом проекте вместо ant+ivy решили начать с Gradle, На текущий момент довольны — зависимости разрешаются, структура проекта специфицирована, однако груви позволяет ее легко «гнуть» в нужную сторону. К недостаткам можно отнести бестолковый (пока?) плагин для идеи.
                0
                А как дела обстоят в случае, если структура проекта иная и ее нельзя изменить? С maven идея сейчас дружит хорошо.
                  0
                  Вообще gradle позволяет делать кастомные проекты (не используя java/war/ear плагины), но при этом многие фишки, например автоматичексий запуск тестов, чекстайла и т.п. придется делать вручную. Если под структурой проекта подразумевается просто расположение исходников и ресурсов, то такие вещи можно подкрутить при помощи source set'ов.
                0
                Коллеги, подскажите старику, далекому от джавы — в терминологии maven что есть nexus? Это какой-то штатный локальный репозиторий, сторонний продукт для создания локальных репозиториев, какая-то настройка мавена для создания локального репозитория? Гугль выдает странное.
            • UFO just landed and posted this here
                0
                Makefile ?:)
                • UFO just landed and posted this here
                  0
                  Насколько знаю для C# используют NAnt или MSBuild
                    +1
                    В С++ используются makefile'ы, конкретно тулчейн 'autotools'. Когда запускается скрипт './configure' (или 'configure.exe'), система анализируется на предмет установленных библиотек, их пути прописываются в общий .h файл, передаются линкеру и компилятору.

                    Откуда в системе библиотеки возьмутся — это отдельный больной вопрос. Для nix и osx есть сстему управления зависимостями. Например 'port install GIMP' при установке проинспектирует зависимости и поставит все библиотеки нужных версий, от которых программа зависит — после чего уже соберет сам GIMP. «Общего решения» типа maven, насколько я знаю для C++ не существует.

                    На практике стараются управление версиями спихнуть на VCS: необходимые версии библиотеки помещаются в локальные репозитории и делается простенький скрипт на python/ruby/perl который устанавливает необходимые переменные окружения для корректной сборки и линковки. Нужные версии библиотек фиксируются через метки в системе контроля версий.
                    • UFO just landed and posted this here
                        0
                        Помимо скриптов configure есть еще CMake, которая умеет делать то же самое + обладает доп. фичами, например содержит в себе кучу модулей для поиска в системе и подключения популярных библиотек, умеет генерировать не только разные makefile, но и проекты для разных IDE (VisualStudio, Code::Blocks, Eclipse CDT). ИМХО освоить ее проще, чем autotools, и проще использовать под windows.
                      –3
                      перестал читать статью после слова репозитарий
                      • UFO just landed and posted this here
                        +1
                        Спасибо за статью. Мы тоже используем maven для организации CI-цикла, вполне довольны. Более подробно свой опыт описывал у себя в блоге – Маленький Билд и его друзья

                        Only users with full accounts can post comments. Log in, please.