PlatformIO Community

"Multiple definition of `main`" error when trying to create a library with dependencies

Hi,

First off, I’m quite new to the PlatformIO ecosystem and embedded systems programming in general, so apologies if this is a silly question.

I have created a library that depends on semver.c by specifying this in the library.json.

{
	"dependencies": [
		{
			"name": "semver",
			"version": "https://github.com/h2non/semver.c.git#bf2ac7567917c84fd2ff7393317a14caafa28796"
		}
	]
}

When I try and use my library in a (esp-idf framework) project however, the project fails to compile with the error

/home/user/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: .pio/build/esp32dev/libde3/libsemver.a(semver_unit.o): in function `main':
/home/user/Profile/tmp/esp32-experiments/platformio/helloworld/.pio/libdeps/esp32dev/semver/semver_unit.c:91: multiple definition of `main'; .pio/build/esp32dev/libde3/libsemver.a(semver_test.o):/home/user/Profile/tmp/esp32-experiments/platformio/helloworld/.pio/libdeps/esp32dev/semver/semver_test.c:677: first defined here

but all I have to do to make it compile is add this file to my main project (not the library) that does nothing and is never included:

#include <semver.h>

void this_is_never_used() {
	semver_t some_pointless_variable = {};
	semver_parse("x", &some_pointless_variable);
}

Does anyone know why this might be happening, and if there’s a better solution to the problem that doesn’t require including an unused file in the main project? Is there a better solution than this that I don’t know about?

It feels like when I use semver.c directly something in the PlatformIO stack is recognizing that I’m not using the test code and is stripping it out, but if I use it only in a library it’s trying to link the test code.

Thanks in advance for any advice! I’m happy to share more complete test projects that reproduce the problem if that would help.

PlatformIO will download the whole repo in the specified version and try to use it as a library, but then…

These files are both fighting to implement the main() function, thus creating the conflict. They are both included in the build because they are not filtered out by the default src_filter expression – thus they’re seen as an ordinary C file in the lib.

Plus if you are using ESP-IDF, the main entry function is app_main(), and no code ever should implement the main() function – that might have unforseen consequences.

The semver_test.c and semver_unit.c seem to implement a program that executes unit tests on the main library code, semver.c and semver.h.

The absolute easiest way to solve your problem is to create a library with only semver.c and .h, that is, in your project, create the folder lib/semver/ and in there, put semver.c and semver.h. That folder is your library folder and you technically don’t even need a library.json description because it’s so simple – it has zero dependencies to anything else but the built-in C library.

However, that of course won’t allow you to specify it as a dependency. Sadly with the current library.json mechanism, you cannot point at some repository that does not build out of the box and fix it up with library.json (that e.g. has srcFilter expression…) so that it would work, it can also be a repository (or a refernece to an uploaded library in the registry). In that case I’d recommend to simply fork the repo https://github.com/h2non/semver.c and either:

  • remove the semver_test.c and semver_unit.c, which eliminates the source of the multiple definitions
  • add a proper library.json definition in which you exclude the aforementioned files by means of a srcFilter expression as referenced above

Then you can reference the fixed library fork in your dependencies.

2 Likes

Thanks so much for the answer @maxgerhardt! I’ll fork semver.c and set the correct srcFilter in library.json. I was hoping to avoid having to fork it, but it makes sense that it’s not working as-is.