cat CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(link)
add_executable(test main.cpp foo-test.cpp)
add_library(lib foo-real.cpp)
target_link_libraries(test PRIVATE lib)
$ cat main.cpp
#include "foo.h"
int main() { return foo(); }
$ cat foo.h
#pragma once
int foo();
$ cat foo-real.cpp
int foo() { return 0; }
$ cat foo-test.cpp
int foo() { return 1; }
$ cmake --build b
[5/5] Linking CXX executable test
$ ./b/test; echo $?
1
почему здесь нет бабаха про multiple definitions: foo@real.cpp, foo@test.cpp ?..
Потому что UB?
ODR проверяет компилятор, линкеру на это плевать, он берёт первый найденный символ.
multiple definitions более менее детектится на винде линкером msvc, на линуксе он то ли не детектит, то ли не всегда
и всё бы ничего, но add_executable(test main.cpp foo-test.cpp foo-real.cpp ) $ cmake --build b [1/1] Linking CXX executable test FAILED: test : && /usr/bin/clang++ CMakeFiles/test.dir/main.cpp.o CMakeFiles/test.dir/foo-test.cpp.o CMakeFiles/test.dir/foo-real.cpp.o -o test && : /usr/bin/ld: CMakeFiles/test.dir/foo-real.cpp.o: in function `foo()': foo-real.cpp:(.text+0x0): multiple definition of `foo()'; CMakeFiles/test.dir/foo-test.cpp.o:foo-test.cpp:(.text+0x0): first defined here
Ну ты сделал какой-то всратый аналог инкрементальной линковки яполагаю
в плюсах нет линковки.
Линкер сначала просматривает локальные объектные файлы, если не находит символ, то начинает просматривать объектные файлы из библиотек по очереди. Если в процессе будут найдены одинаковые символы, то будет ошибка multiple definition, но в твоём случае её нет, т.к. все символы из библиотеки есть и в локальных объектных файлах.
вроде совпадает с тем, что я вычитал на SO спасибо, буду учитывать
Обсуждают сегодня