[Boost.Test] linking with shared lib (cannot find main)
From what I can tell, g++ is failing to find the main the executable because it is attempting to compile one of my unit test files first. This may or may not be the case; either way, I would appreciate some help or
Hi all, I have been using Boost.Test for about a month now. Big fan so far, except for the atrocious compilation times, hence why I am moving toward using the shared library. using b2 to build and install Boost.Test's libs was simple enough, though after making the noted changes here: https://www.boost.org/doc/libs/1_72_0/libs/test/doc/html/boost_test/adv_scen... to customize the module's entry point, g++ cannot find the main executable: Undefined symbols for architecture x86_64: "_main", referenced from: implicit entry/start for main executable ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [Guest_T] Error 1 I tried digging through the docs for more information, but I came up short. For more context, I have written unit tests for each of my classes. For example, if my classes were A, B, and C, I would have A_T.cpp, B_T.cpp, and C_T.cpp for unit tests. - Should each of the unit tests have their own main() function? (I would think not..) - If not, how do I instruct g++ to first compile main.cpp before attempting to compile anything else? If you are curious, here are the contents of my Makefile: PROG := main CC := g++ SDIR := ../src PKG_DIRS := $(shell ls $(SDIR)) CXXFLAGS = -v -Wall -std=c++11 -I$(SDIR_TEST) \ $(addprefix -I$(SDIR)/,$(PKG_DIRS)) -I$(BOOST_ROOT) \ -L$(BOOST_LIBS) -Wl,-rpath,$(BOOST_LIBS) -lboost_unit_test_framework ODIR_TEST = ./bin SDIR_TEST = ./src OUTDIR = ./execs ODIR = ../sim/bin TEST_EXEC_NAMES = $(notdir $(basename $(wildcard $(SDIR_TEST)/*.cpp))) $(OUTDIR)/$(PROG) : $(SDIR_TEST)/main.cpp $(CC) $(CXXFLAGS) -o $@ $< $(OUTDIR)/$(PROG) : $(TEST_EXEC_NAMES) $(CC) $(CXXFLAGS) -o $@ $^ % : $(SDIR_TEST)/%.cpp $(CC) $(CXXFLAGS) -o $(OUTDIR)/$@ $^ direction as to what I should read to learn more about this. Let me know if you need more info. Thanks in advance. - AJ
Okay, so I've actually made considerable progress. g++ can now find the main entry point and all my object files are being compiled and placed where I want them. I'm even noticing the compilation speedup from using the shared library, which is super cool. I have (for the most part) transitioned my unit test translation units from "automatic" to "manual". My current approach for manual test registration is as follows: - have an init_test_suite() function in each translation unit that: 1) creates a test suite 2) adds all test cases from that translation unit to the test suite 3) adds the test suite to the master test suite - include test translation units in main.cpp - have a register_test_suites() function in main.cpp that calls the init_test_suite() function for each translation unit being tested As one would expect from including a bunch of test translation units in main.cpp (where several of them include files that are included by other test translation units), I am running into redefinition errors. This does not surprise me. I am wondering: what would be a good modularized approach to calling the init_test_suite() function defined in each of my test translation units from main.cpp? Should I have test class header files with include guards, and then include those files in main.cpp? Sort of wondering what others have done in the past with manual test registration to avoid redefinitions and maximize encapsulation. Thanks in advance. -AJ On Fri, Feb 28, 2020 at 6:50 PM Andrew McFarlane < andrew.mcfarlane52@gmail.com> wrote:
Hi all,
I have been using Boost.Test for about a month now. Big fan so far, except for the atrocious compilation times, hence why I am moving toward using the shared library.
using b2 to build and install Boost.Test's libs was simple enough, though after making the noted changes here:
https://www.boost.org/doc/libs/1_72_0/libs/test/doc/html/boost_test/adv_scen...
to customize the module's entry point, g++ cannot find the main executable:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Guest_T] Error 1
I tried digging through the docs for more information, but I came up short.
For more context, I have written unit tests for each of my classes. For example, if my classes were A, B, and C, I would have A_T.cpp, B_T.cpp, and C_T.cpp for unit tests.
- Should each of the unit tests have their own main() function? (I would think not..)
- If not, how do I instruct g++ to first compile main.cpp before attempting to compile anything else?
If you are curious, here are the contents of my Makefile:
PROG := main
CC := g++
SDIR := ../src
PKG_DIRS := $(shell ls $(SDIR))
CXXFLAGS = -v -Wall -std=c++11 -I$(SDIR_TEST) \
$(addprefix -I$(SDIR)/,$(PKG_DIRS)) -I$(BOOST_ROOT) \
-L$(BOOST_LIBS) -Wl,-rpath,$(BOOST_LIBS) -lboost_unit_test_framework
ODIR_TEST = ./bin
SDIR_TEST = ./src
OUTDIR = ./execs
ODIR = ../sim/bin
TEST_EXEC_NAMES = $(notdir $(basename $(wildcard $(SDIR_TEST)/*.cpp)))
$(OUTDIR)/$(PROG) : $(SDIR_TEST)/main.cpp
$(CC) $(CXXFLAGS) -o $@ $<
$(OUTDIR)/$(PROG) : $(TEST_EXEC_NAMES)
$(CC) $(CXXFLAGS) -o $@ $^
% : $(SDIR_TEST)/%.cpp
$(CC) $(CXXFLAGS) -o $(OUTDIR)/$@ $^
From what I can tell, g++ is failing to find the main the executable because it is attempting to compile one of my unit test files first. This may or may not be the case; either way, I would appreciate some help or direction as to what I should read to learn more about this.
Let me know if you need more info.
Thanks in advance.
- AJ
On 29.02.20 03:50, Andrew McFarlane via Boost-users wrote:
Hi all,
I have been using Boost.Test for about a month now. Big fan so far, except for the atrocious compilation times, hence why I am moving toward using the shared library.
using b2 to build and install Boost.Test's libs was simple enough, though after making the noted changes here: https://www.boost.org/doc/libs/1_72_0/libs/test/doc/html/boost_test/adv_scen...
Hi, In 99.9% of the time, you do not need this functionality. The automatic test registration just works, and with any variants (shared included). For shared, you need to define BOOST_TEST_DYN_LINK=1 and a single translation unit /per executable/ containing either BOOST_TEST_MAIN or BOOST_TEST_MODULE. Can I help getting on tracks? Raffi
participants (2)
-
Andrew McFarlane
-
Raffi Enficiaud