I am trying to build a very simple C++ program using the Maven NAR plugin. I've set up a Maven module for building a shared library, and another for linking in the library and building an executable that uses it. Building on a Mac works great and I can run the program. Unfortunately, building on Windows (XP) with MS Visual C++ (free version) fails with a linker error. The only difference in configurations between the two machines (other than OS and compiler) is that I run vcvars32.bat before building with Maven on the Windows machine. Here's the error I am getting:
main.obj : error LNK2019: unresolved external symbol "public: int __thiscall
Calculator::add(int,int)" (?add@Calculator@@QAEHHH@Z) referenced in function
_main executable.exe : fatal error LNK1120: 1 unresolved externals
The linker command spit out by the NAR plugin looks like this:
link /MANIFEST /NOLOGO /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /OUT:executable.exe
C:\dev\Projects\trunk\executable\target\nar\obj\x86-Windows-msvc\main.obj
I expect it should have the DLL generated by my shared library module listed, but its not there. The DLL's NAR is unpacked in the executable's target directory, as it should be.
Any help in configuring the NAR plugin for Windows would be appreciated. Alternately a command line showing how to properly execute the linker would be useful so I can backfill the NAR configuration to achieve it. Thanks.
My shared library module:
Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
class Calculator {
public:
int add(int first, int second);
};
#endif
Calculator.cc
#include "Calculator.h"
int Calculator::add(int first, int second) {
return first + second;
}
pom.xml (snippets):
<groupId>com.mycompany</groupId>
<artifactId>library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>nar</packaging>
...
<plugin>
<artifactId>maven-nar-plugin</artifactId>
<version>2.1-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<libraries>
<library>
<type>shared</type>
</library>
</libraries>
</configuration>
</plugin>
My executable module:
main.cc
#include <iostream>
#include "Calculator.h"
int main() {
Calculator calculator;
std::cout << calculator.add(2, 5) << std::endl;
}
pom.xml (snippets)
<groupId>com.mycompany</groupId>
<artifactId>executable</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>nar</packaging>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>library</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>nar</type>
</dependency>
...
<plugin>
<artifactId>maven-nar-plugin</artifactId>
<version>2.1-SNAPSHOT</version>
<extensions>true</extensions>
<configuration>
<libraries>
<library>
<type>executable</type>
</library>
</libraries>
</configuration>
</plugin>
Answering my own question.
A colleague of mine dug into the murkier recesses of his brain and said he recalled something like "dicklespeck" being needed. That sounded bizarre so I put it in the "if all else fails I'll look that up" bucket. After all else failed, I came back to it and Googled various spellings which revealed that he was correct. If I add this abomination to my class declaration:
__declspec(dllexport)
The DLL successfully links with the executable.
So "fixing" the Calculator header file like so is the solution:
#ifndef CALCULATOR_H
#define CALCULATOR_H
class __declspec(dllexport) Calculator {
public:
int add(int first, int second);
};
#endif
Yuck! I can #define
that thing away for non-windows builds, but still - yuck!
Someone please tell me this isn't the only solution.