C++ 在makefile中创建一个库文件然后编译

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9593286/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:02:08  来源:igfitidea点击:

Creating a library file in makefile and compiling after that

c++makefileg++mpic++

提问by Mare

My problem is fairly easy but I just don't know how to solve it. I know how to compile and library and link against it if I'm not using a make file because then I can just call ar separately and everything goes right.

我的问题很简单,但我只是不知道如何解决它。如果我不使用 make 文件,我知道如何编译和库并链接它,因为这样我就可以单独调用 ar 并且一切正常。

Anyway I'm using a petsclibrary and I'm using a makefile what they provided:

无论如何,我使用的是petsc库,我使用的是他们提供的 makefile:

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 will be -rv as a default so where should I provide such a information as

ARFLAGS 将 -rv 作为默认值,所以我应该在哪里提供这样的信息

ar -rv libclassdll.a class.o

and where should I add -L./-lclassdll ?

我应该在哪里添加 -L./-lclassdll ?

I'm quite a rookie with makefiles so that's why I'm a bit lost here :<

我是一个使用 makefile 的新手,所以这就是我在这里有点迷失的原因:<

I tried to change the line to

我试图将线路更改为

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

and then my compiling command seems to be mpicxx -o myProgram main.o class.o /usr/bin/ar/ libclassdll.a class.o -L ( a lot of linking here ) and at least it says: g++ classdll.a no such a file or dir.

然后我的编译命令似乎是 mpicxx -o myProgram main.o class.o /usr/bin/ar/libclassdll.a class.o -L(这里有很多链接),至少它说:g++ classdll.a没有这样的文件或目录。

So it doesn't generate even a lib file for me. So any ideas will be really appreciated.

所以它甚至不会为我生成一个 lib 文件。所以任何想法都将不胜感激。

A new problem when I uploaded makefile on the different machine, my current makefile looks like this

我在另一台机器上上传 makefile 时出现的新问题,我当前的 makefile 看起来像这样

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}

That works on one machine but other machine gives following error

这适用于一台机器,但另一台机器出现以下错误

/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

I did change the paths of course but I guess that indicates other kind of problem because even if I type "g++ -shared -Wl,-soname,libmyclass.so.1 -o libmyclass.so.1.0 MyClass.o" or "g++ -fPIC -share... " I'll get the same error.

当然,我确实更改了路径,但我想这表明存在其他类型的问题,因为即使我输入“g++ -shared -Wl,-soname,libmyclass.so.1 -o libmyclass.so.1.0 MyClass.o”或“g++” -fPIC -share...” 我会得到同样的错误。

回答by Beta

Ideally you should construct the library first, then use it, just as you would "by hand".

理想情况下,您应该先构建库,然后使用它,就像“手动”一样。

To construct (or update) the library, you need a rule something like this:

要构建(或更新)库,您需要一个类似这样的规则:

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

Or more concisely, like this:

或者更简洁地说,像这样:

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

Then the rule for myProgrambecomes:

那么规则myProgram变为:

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

or better:

或更好:

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

So in your makefile, you would replace

所以在你的 makefile 中,你会替换

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

with

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

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

There are other refinements you can make, but that should be enough for now.

您还可以进行其他改进,但现在应该足够了。

回答by Kaz

Make myProgram depend on main.o and on the libclass.a (don't call it libclassdll.a; it is not a DLL, but a static library).

让 myProgram 依赖于 main.o 和 libclass.a(不要称它为 libclassdll.a;它不是一个 DLL,而是一个静态库)。

General gist of the solution:

解决方案的一般要点:

# $@ 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