Создание файла библиотеки в makefile и компиляция после этого

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

В любом случае я использую библиотеку petsc и использую make-файл, который они предоставили:

CFLAGS          = 
FFLAGS          = 
CPPFLAGS        = 
FPPFLAGS        =
LOCDIR          = /home/user/.../.../   # Working folder
EXAMPLESC       = main.cpp class.cpp        #.cpp file names here
EXAMPLESF       =
#MANSEC          = Mat I don't know what this is but it seems to work without it.

include ${PETSC_DIR}/conf/variables
include ${PETSC_DIR}/conf/rules

myProgram: main.o class.o  chkopts
    -${CLINKER}  -o myProgram main.o class.o ${PETSC_MAT_LIB}
    ${RM} main.o class.o

include ${PETSC_DIR}/conf/test

ARFLAGS будет -rv по умолчанию, поэтому где я должен предоставить такую ​​информацию, как

ar -rv libclassdll.a class.o

и куда мне добавить -L./-lclassdll?

Я довольно новичок с make-файлами, поэтому я немного потерян здесь:<

Я пытался изменить строку на

myProgram: main.o class.o  chkopts
    -${CLINKER}  -o myProgram main.o class.o ${AR} libclassdll.a class.o ${PETSC_MAT_LIB}
    ${RM} main.o class.o

и затем моя команда компиляции выглядит как mpicxx -o myProgram main.o class.o /usr/bin/ar/ libclassdll.a class.o -L (здесь много ссылок) и по крайней мере она говорит: g++ classdll.a нет такого файла или реж.

Так что он не генерирует даже файл lib для меня. Так что любые идеи будут по достоинству оценены.

Новая проблема, когда я загрузил make-файл на другой компьютер, мой текущий make-файл выглядит так

LibMyClass.so: MyClass.o  chkopts
    -${CLINKER}  -shared -Wl,-soname,${SONAME} -o ${VERS}   *.o  ${PETSC_MAT_LIB}

    mv ${VERS} ${LIBADD}
    ln -sf ${LIBADD}${VERS} ${LIBADD}${SOWOV}
    ln -sf ${LIBADD}${VERS} ${LIBADD}${SONAME}

Это работает на одной машине, но другая машина дает следующую ошибку

/usr/bin/ld: MyClass.o: relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
MyClass.o: could not read symbols: Bad value

Конечно, я изменил пути, но, думаю, это указывает на другие проблемы, потому что даже если я наберу "g++ -shared -Wl,-soname,libmyclass.so.1 -o libmyclass.so.1.0 MyClass.o" или "g++ -fPIC -share... "Я получу ту же ошибку.

2 ответа

Решение

В идеале вы должны сначала создать библиотеку, а затем использовать ее так же, как "вручную".

Чтобы создать (или обновить) библиотеку, вам нужно правило примерно так:

libclassdll.a: class.o
    ar -rv libclassdll.a class.o

Или более кратко, как это:

libclassdll.a: class.o
    ar $(ARFLAGS) $@ $^

Тогда правило для myProgram будет выглядеть так:

# Assuming CLINKER is something civilized, like gcc
myProgram: main.o libclassdll.a  chkopts
    -${CLINKER} -o myProgram main.o -L. -lclassdll ${PETSC_MAT_LIB}

или лучше:

myProgram: main.o libclassdll.a  chkopts
    -${CLINKER} -o $@ $< -L. -lclassdll ${PETSC_MAT_LIB}

Таким образом, в вашем make-файле вы должны заменить

myProgram: main.o class.o  chkopts
    -${CLINKER}  -o myProgram main.o class.o ${PETSC_MAT_LIB}
    ${RM} main.o class.o

с

myProgram: main.o libclassdll.a  chkopts
    -${CLINKER} -o $@ $< -L. -lclassdll ${PETSC_MAT_LIB}

libclassdll.a: class.o
    ar $(ARFLAGS) $@ $^

Вы можете внести другие улучшения, но этого должно быть достаточно.

Сделайте myProgram зависимым от main.o и libclass.a (не называйте это libclassdll.a; это не DLL, а статическая библиотека).

Общая суть решения:

# $@ means "the target of the rule"
# $^ means "the prerequisites: main.o and libclass.a"

myProgram: main.o libclass.a
        $(CC) -o $@ $^ # additional arguments for other libraries, not built in this make

libclass.a: class.o
        # your $(AR) command goes here to make the library
Другие вопросы по тегам