Я пытаюсь скомпилировать простую программу hello world:
main.cpp
#include <iostream>
#include <test/t.hpp>
int main( int argc , char** args )
{
std::cout << test() << std::endl;
int x;
std::cin >> x;
return 0;
}
Тест / t.hpp
#ifndef TEST_T_HPP_INCLUDED
#define TEST_T_HPP_INCLUDED
int test();
#endif // TEST_T_HPP_INCLUDED
Тест / t.cpp
#include <test/t.hpp>
int test()
{
return 42;
}
С этим makefile:
executable_name = testapp
cpp_compiler = g++
cpp_compiler_flags += -std=c++14
cpp_compiler_flags += -g
cpp_linker_flags += -g
linked_libraries +=
included_directories += -I./src/
source_dir = src
source_files += main.cpp
source_files += test/t.cpp
object_dir = obj
object_files = $(addprefix $(object_dir)/,$(source_files:=.o))
directories = $(sort $(foreach i,$(object_files),$(dir $i)))
source_files := $(addprefix $(source_dir)/,$(source_files))
all: make_directories tool
tool: $(object_files)
$(cpp_compiler) $(cpp_linker_flags) -o $(executable_name) $(object_files) $(linked_libraries)
$(object_files): $(source_files)
$(cpp_compiler) $^ $(cpp_compiler_flags) $(included_directories) -o $@
make_directories:
@sh -c \
'for d in $(directories); do \
if [ ! -d $$d ]; \
then echo mkdir -p $$d; mkdir -p $$d; \
fi \
done'
С помощью инструментов TDM-GCC-4.8.1, поставляемых с CodeBlocks 13.12 (и mingw32-make)
Но я получаю более 10000 ошибок, как это:
obj/src/main.cpp.o:crtend.c:(.text+0x26a80): first defined here
obj/src/test/t.cpp.o:crtend.c:(.text+0x26880): multiple definition of `std::__us
e_cache<std::__numpunct_cache<char> >::operator()(std::locale const&) const'
obj/src/main.cpp.o:crtend.c:(.text+0x26880): first defined here
obj/src/test/t.cpp.o:crtend.c:(.text+0x350d0): multiple definition of `std::ostr
eambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambu
f_iterator<char, std::char_traits<char> > >::_M_insert_float<double>(std::ostrea
mbuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, char, double
) const'
obj/src/main.cpp.o:crtend.c:(.text+0x350d0): first defined here
obj/src/test/t.cpp.o:crtend.c:(.text+0x35ee0): multiple definition of `std::num_
put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std:
:ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, doubl
e) const'
obj/src/main.cpp.o:crtend.c:(.text+0x35ee0): first defined here
Я предполагаю, что это ошибки компоновщика, поскольку за доли секунды я вижу исходные файлы для компиляции.
Что я здесь пропустил?
РЕДАКТИРОВАТЬ
это правило заставило его работать:
$(object_files): $(object_dir)/%.o : $(source_dir)/%
$(cpp_compiler) -c $^ $(cpp_compiler_flags) $(included_directories) -o $@
Проблема здесь:
$(object_files): $(source_files)
$(cpp_compiler) $^ $(cpp_compiler_flags) $(included_directories) -o $@
Этот рецепт делает все исходные файлы предпосылок каждый объектный файл. Поэтому, когда Make пытается построить main.o
он выполняет
g++ ... main.cpp test/t.cpp -o main.o
Все переходит в main.o
, а также все переходит в t.o
поэтому, когда компоновщик пытается связать объектные файлы вместе, он встречает несколько определений повсюду.
Попробуйте правило статического шаблона:
$(object_files): $(object_dir)/%.o: %.cpp
$(cpp_compiler) $< $(cpp_compiler_flags) $(included_directories) -o $@
РЕДАКТИРОВАТЬ:
Постскриптум вам, возможно, придется помочь найти t.cpp
:
vpath %.cpp test