Как использовать и собрать make-файл для ссылки scip на C? - PullRequest
4 голосов
/ 14 февраля 2020

Я очень новичок в C. Мне просто нужно использовать одну из функций в scip. Я сделал файл make, как показано ниже:

SCIPDIR=$/Users/amin/Documents/cProgram/scipoptsuite-6.0.2/scip

include $(SCIPDIR)/make/make.project

%.o: %.c
    $(CC) $(FLAGS) $(OFLAGS) $(BINOFLAGS) $(CFLAGS) -c $<

all: cmain

cmain: cmain.o
    $(LINKCXX) cmain.o $(LINKCXXSCIPALL) $(LDFLAGS) $(LINKCXX_o) cmain

мой cmain. c файл выглядит так:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*                                                                           */
/*                  This file is part of the program and library             */
/*         SCIP --- Solving Constraint Integer Programs                      */
/*                                                                           */
/*    Copyright (C) 2002-2019 Konrad-Zuse-Zentrum                            */
/*                            fuer Informationstechnik Berlin                */
/*                                                                           */
/*  SCIP is distributed under the terms of the ZIB Academic License.         */
/*                                                                           */
/*  You should have received a copy of the ZIB Academic License              */
/*  along with SCIP; see the file COPYING. If not visit scip.zib.de.         */
/*                                                                           */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**@file   GMI/src/cmain.c
 * @brief  main file for GMI cut example
 * @author Marc Pfetsch
 */

/*--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/

#include <scip/scip.h>
#include <scip/scipdefplugins.h>

/** reads parameters */
static
SCIP_RETCODE readParams(
   SCIP*                 scip,               /**< SCIP data structure */
   const char*           filename            /**< parameter file name, or NULL */
   )
{
   if ( filename != NULL )
   {
      if ( SCIPfileExists(filename) )
      {
         SCIPinfoMessage(scip, NULL, "reading parameter file <%s> ...\n", filename);
         SCIP_CALL( SCIPreadParams(scip, filename) );
      }
      else
         SCIPinfoMessage(scip, NULL, "parameter file <%s> not found - using default parameters.\n", filename);
   }
   else if ( SCIPfileExists("scipgmi.set") )
   {
      SCIPinfoMessage(scip, NULL, "reading parameter file <scipgmi.set> ...\n");
      SCIP_CALL( SCIPreadParams(scip, "scipgmi.set") );
   }

   return SCIP_OKAY;
}

/** starts SCIP */
static
SCIP_RETCODE fromCommandLine(
   SCIP*                 scip,               /**< SCIP data structure */
   const char*           filename            /**< input file name */
   )
{
   /********************
    * Problem Creation *
    ********************/

   SCIPinfoMessage(scip, NULL, "read problem <%s> ...\n\n", filename);
   SCIP_CALL( SCIPreadProb(scip, filename, NULL) );

   /*******************
    * Problem Solving *
    *******************/

   /* solve problem */
   SCIPinfoMessage(scip, NULL, "solve problem ...\n\n");
   SCIP_CALL( SCIPsolve(scip) );

   SCIPinfoMessage(scip, NULL, "primal solution:\n");
   SCIP_CALL( SCIPprintBestSol(scip, NULL, FALSE) );

   /**************
    * Statistics *
    **************/

   SCIPinfoMessage(scip, NULL, "Statistics:\n");
   SCIP_CALL( SCIPprintStatistics(scip, NULL) );

   return SCIP_OKAY;
}

/** starts user interactive mode */
static
SCIP_RETCODE interactive(
   SCIP*                 scip                /**< SCIP data structure */
   )
{
   SCIP_CALL( SCIPstartInteraction(scip) );

   return SCIP_OKAY;
}

/** creates a SCIP instance with default plugins, evaluates command line parameters, runs SCIP appropriately,
 *  and frees the SCIP instance
 */
static
SCIP_RETCODE runSCIP(
   int                   argc,               /**< number of shell parameters */
   char**                argv                /**< array with shell parameters */
   )
{
   SCIP* scip = NULL;

   /*********
    * Setup *
    *********/

   /* initialize SCIP */
   SCIP_CALL( SCIPcreate(&scip) );

   /* we explicitly enable the use of a debug solution for this main SCIP instance */
   SCIPenableDebugSol(scip);

   /***********************
    * Version information *
    ***********************/

   SCIPprintVersion(scip, NULL);
   SCIPinfoMessage(scip, NULL, "\n");

   /* include default SCIP plugins */
   SCIP_CALL( SCIPincludeDefaultPlugins(scip) );

   /**************
    * Parameters *
    **************/

   if ( argc >= 3 )
   {
      SCIP_CALL( readParams(scip, argv[2]) );
   }
   else
   {
      SCIP_CALL( readParams(scip, NULL) );
   }

   /**************
    * Start SCIP *
    **************/

   if ( argc >= 2 )
   {
      SCIP_CALL( fromCommandLine(scip, argv[1]) );
   }
   else
   {
      SCIPinfoMessage(scip, NULL, "\n");

      SCIP_CALL( interactive(scip) );
   }

   /********************
    * Deinitialization *
    ********************/

   SCIP_CALL( SCIPfree(&scip) );

   BMScheckEmptyMemory();

   return SCIP_OKAY;
}

/** main method starting SCIP */
int main(
   int                   argc,               /**< number of arguments from the shell */
   char**                argv                /**< array of shell arguments */
   )
{
   SCIP_RETCODE retcode;

   retcode = runSCIP(argc, argv);
   if ( retcode != SCIP_OKAY )
   {
      SCIPprintError(retcode);
      return -1;
   }

   return 0;
}

Теперь в каталоге, где у меня есть эти 2 файла, я запускаю Сделать, но это не работает, я получаю сообщение об ошибке: No such file or directory

make: *** No rule to make target `Users/amin/Documents/cProgram/scipoptsuite-6.0.2/scip/make/make.project'.  Stop.

Я просто пытался следовать инструкциям, которые кто-то предложил. Пожалуйста, помогите мне, если можете. что мне делать?

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Вы хотите разделить две вещи

  1. Сборка SCIP
  2. Сборка и связывание вашей программы.

Сборка SCIP

Обычно можно было бы go узнать об этой библиотеке и установить ее с помощью менеджера пакетов в большинстве UNIX -подобных систем или сделать make install, чтобы скопировать ее в систему. Затем заголовочные файлы et c. будет автоматически найден. Если вы не хотите делать это, а скорее «связываете» SCIP с вашей программой, вы обычно распространяете копию или связываете копию этой версии для вашей программы (копию кода в вашем исходном дереве, например, в разделе «external» или используя git подмодулей, ...). В любом случае, однако, вы не хотите, чтобы путь к SCIP был абсолютным. В качестве примера используйте этот макет:

./
-- external/SCIP
-- cmain.c
-- Makefile

В Makefile вы можете установить SCIPDIR как это для последующего использования:

SCIPDIR := "./external/SCIP"

Сначала, однако, вы должны понимать, как строить вручную. Для этого вы вводите «./external/SCIP» и собираете библиотеку в соответствии с инструкциями в файле Readme (часто делая что-то вроде ./configure && make && make install). Если вы хотите автоматизировать это, вы можете сделать это из вашего основного файла. Для этого вы можете добавить «фальшивую» цель (ie. Цель, которая не будет точно создавать один вывод, но создаст все зависимости), которую мы будем называть dep:

dep:
        cd $(SCIPDIR); ./configure
        $(MAKE) -C $(SCIPDIR)

.PHONY: dep

( спасибо @UpAndAdam за указание на то, что вы должны изменить CWD перед запуском скрипта configure)

Для этого мы рекурсивно вызываем make для нашего подпроекта. Мы не хотим устанавливать файлы в масштабе всей системы, поэтому мы просто собираем библиотеку.

Сборка вашей программы

Теперь мы добавим два правила-шаблона, которые определяют, как создавать и связывать C программы. GNU / Make (тот, который вы используете) уже имеет встроенные суффиксные правила, но он уже по умолчанию знает, как создавать C программы, но с суффиксными правилами сложно разобраться, и вы уже используете другие функции GNU / Make, поэтому мы также можем использовать шаблонные правила, которые примерно эквивалентны, и отключить встроенные правила:

%.o: %.c
        $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%: %.o
         $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LDLIBS)

.SUFFIXES:

Небольшое замечание: мы компилируем один объектный файл из одного c файла путем сопоставления с шаблоном. Я использовал стандартные переменные, CPPFLAGS (препроцессор C, а не C ++!), CFLAGS (флаги компилятора и функций C) и перечислил все опции перед аргументом без опции $<, который будет содержать (первую) указанную зависимость например "CMain. c". Не все C компиляторы допускают смешивание опций и аргументов.

Для линковки я делаю то же самое, но я перечисляю библиотеки, с которыми мы хотим связать последнюю. Это важно, компилятор classi c C будет отбрасывать любые библиотеки, перечисленные там, если в списке не было ранее объектов, зависящих от этой переменной.

Теперь, когда мы знаем, как построить Программа generi c C, мы на самом деле хотим сначала собрать SCIP, затем вашу программу и связать ее. Для этого мы создадим новую зависимость PHONY под названием «all», которая будет делать именно это:

all: dep cmain

.PHONY: dep all

Однако, если мы сейчас выполним make all, она потерпит неудачу, поскольку мы еще не сделали указал путь включения et c. Для этого мы установили переменные, которые мы использовали ранее, на необходимые значения (я угадал указанный путь c, так как я на мобильном телефоне):

CPPFLAGS += -I$(SCIPDIR)/include
LDFLAGS += -L$(SCIPDIR)
LDLIBS += -lscip

Собираем все вместе

Теперь это должно работать, более или менее. Одна вещь заключается в том, что в качестве цели по умолчанию обычно используется all, то есть первая цель, указанная в файле Makefile. Итак, мы пишем:

CPPFLAGS += -I$(SCIPDIR)/include
LDFLAGS += -L$(SCIPDIR)
LDLIBS += -lscip

all: dep cmain

%.o: %.c
    $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

%: %.o
    $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $^ $(LDLIBS)

dep:
    cd $(SCIPDIR); ./configure.sh
    $(MAKE) -C $(SCIPDIR)

.PHONY: dep all
.SUFFIXES:

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

3 голосов
/ 14 февраля 2020

Вы делаете это неправильно.

Сначала без цели первый рецепт называется вызываемым, поэтому цель all должна go первая.

секунда: не include этот другой файл и удалите почти все, кроме переменной каталога и all target

, которые вам просто нужно добавить в переменную LD_FLAGS, и правила автоматизации c свяжутся для вас. если проект scip не принесет кучу переменных, в которых вы нуждаетесь, я не знаю, почему вам нужно было бы включить сюда информацию о его файле make.

Также следует отметить, что текущий путь, который вы загрузили в переменную в назначении был введен неверный начальный знак $, и для связи с ним нам необходимо убедиться, что его полный путь к libscip.so (или libscip.a)

т.е. LD_FLAGS+=-L${DIR_containing_libscip.so} -lscip

вам также может понадобиться указать на заголовочные / включаемые файлы:

CPP_FLAGS+=-I${DIR_before_includes_of_scip}/include (если они включены как <scip/foo>. Или без /include и идти вверх, если они должны быть включены так же, как <foo>, это зависит от стиля проектов. Большинство проектов используют шаблон /include/projname, чтобы эффективно сохранять проект в пространстве имен для включаемых файлов, чтобы избежать коллизий.

, что должно быть при условии, что все остальное построено и установлено, и в scip нет ничего особенного, что мне нужно знать о ...

...