Есть проект, который собирается с помощью Cmake компилятором студии. В нем есть такая строка: Код (Text): set(COMPILE_OPTIONS /W3 /Ox /Ob2 /Os /GF /MD /GS- /Gy /MP $<$<CONFIG:Debug>:/Zi> /arch:$<IF:$<BOOL:${CMAKE_CL_64}>,AVX,SSE>) Кто может подсказать по таким вопросам: 1. Что значит строка "/arch:$<IF:$<BOOL:${CMAKE_CL_64}>,AVX,SSE>) " ? Если компилятор 64 битный, то собирать с поддержкой AVX? А если 32 битный, то будет SSE или ничего? 2. Почему, когда собираешь с поддержкой AVX 64 битную прогу, она крашится на виртуалках? Какой-то инструкции там нет или что? И как это можно обойти, что указать чтобы собиралось нормально?
1. Если компилятор 64 битный, то собирать с поддержкой AVX, а если 32 битный, то будет SSE. 2. Должно работать. Надо посмотреть код исключения при вылете, если действительно 0xC000001D (invalid instruction code), то, вероятно, очень древняя виртуалка, пора обновляться.
darkdevel, по пункту 2 - падает на инструкции вида Код (ASM): vpxor xmm0, xmm0, xmm0 , вроде не очень древние ВМ, а в 2018 году и на динчеке падало. менял в настройках проекта на /arch:IA32 , работает вроде, но решение так себе, имхо.
ОС, конечно, 7 с SP или новее. А какая виртуалка? У меня VMware, в ней надо не забывать обновлять Hardware Compatibility гостевых ОС. Кстати, а соответствующий бит в cpuid выставлен? Если нет, то нечего и вызывать неизвестные инструкции
darkdevel, виртуалбокс. так я откуда знаю, я же не на Асме пишу; все вопросы к студии, че она там вставляет.
Имеется ввиду что когда набор инструкций (AVX, SSE и др) поддерживается процессором он в cpuid выставляет определенные биты (какие именно можно смотреть в мануалах), таким образом по этим битам можно проверить поддерживаются ли инструкции.
Все верно, подробнее и понятным языком описано на SO: https://stackoverflow.com/questions...pport-require-which-cpu-multimedia-extensions Использовать асм не придется, в компиляторе студии предусмотрены intrinsics: https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex и даже есть WinAPI https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenabledxstatefeatures Для коммерческого софта хорошим тоном будет проверить набор инструкций и заранее сообщить end-user, что его железо не соответствует системным требованиям, либо иметь две реализации алгоритма. Инструкции не самые новые, но какие только конфигурации не попадаются при саппорте, даже на васме есть адепты секты ХР. Виртуалбоксом не пользовался, но пишут, что можно проверить так: VBoxManage getextradata $VMname enumerate, дальше смотрим VBoxInternal/CPUM/IsaExts/AVX2
Carnival, darkdevel, спасибо. Значит, надо отключать это в студии и всё. студия не проверяет ничего, тупо вставляет эти инструкции.
Интересно взглянуть на код ошибки: если AVX поддерживается физическим процессором, он будет поддерживаться и виртуальным, и отключить поддержку расширений нельзя. Даже если сбросить биты в CPUID, отвечающие за SSE/AVX/etc., эти инструкции всё равно будут доступны для выполнения. Покажи код ошибки и ассемблерный кусок, где вылетает эксепшн (и отметь там RIP) - возможно, падает не из-за виртуалки или не там, где думаешь.
VirtualBox в мануалах предлагает отключение различных расширений, как пример: To provide SSE 4.1/SSE 4.2 support to guests, the host CPU has to implement these instruction sets. The instruction sets are exposed to guests by default, but it is possible to disable the instructions for certain guests by using the following commands: $ VBoxManage setextradata VM-name \ VBoxInternal/CPUM/IsaExts/SSE4.1 0 $ VBoxManage setextradata VM-name \ VBoxInternal/CPUM/IsaExts/SSE4.2 0 These are per-VM settings which are enabled by default. Я сам не пользовался VirtualBox, но не вижу проблемы программно реализовать подобную фичу: поставить маски в контрольных регистрах гостевой ОС. Если ОС не поставила биты, подтверждающие поддержку того или иного instruction set, то процессор будет вести себя, как будто "не умеет": генерировать #ud. Если указываешь компилятору использовать расширенный набор инструкций, добавь проверку сам, без опции компилятор не будет вставлять лишнего (хотя после перехода разработки VS на Agile какие там только баги не встречаются).
Кстати, нагуглился очень простой способ проверить поддержку инструкций в рантайме: Код (C): #include <stdio.h> extern "C" int __isa_available; int main() { printf("__isa_available: %d\n", __isa_available); } Значения переменной как раз соответствуют опциям компилятора: Код (C): enum ISA_AVAILABILITY { __ISA_AVAILABLE_X86 = 0, __ISA_AVAILABLE_SSE2 = 1, __ISA_AVAILABLE_SSE42 = 2, __ISA_AVAILABLE_AVX = 3, __ISA_AVAILABLE_ENFSTRG = 4, __ISA_AVAILABLE_AVX2 = 5, __ISA_AVAILABLE_AVX512 = 6, }; Или развернутый вариант с cpuid: https://github.com/Mysticial/FeatureDetector Имхо, надо пользоваться современными инструкциями везде, где это возможно. Если еще не окончательно забил на изначальный вопрос, запусти детектор на хосте и в госте. Думаю, проблема в конкретной виртуалке.
Вернулся к этому вопросу, хотя вижу, что проще забить и отключить.. Вот скрин. Примерно так падает. 2012 винда. Я все равно не пойму; ну вот собрал я ехе , там уже есть внутри эти новые инструкции. Это же не питон или какой-то JIT, что даст проверка? Я же не могу знать, будет это на машине юзера или нет.
Кто знает, как добавить в CMAKE инклуд .def файла? Что-то смотрел в документации, ничего не работает. Суть - есть проект, который билдится этим самым cmake, и нужно чтобы в дллке был экспорт . Если просто в коде указать через declspec dllexport, то функция экспортируется вида в формате с _Function@4 , что неприемлемо. Только деф файл дает как надо имя (Function).
Если очень хочется сделать dll именно с def файлом, то так же, как и обычно - передать в опции линкеру. Например, для студии будет так: Код (Text): if ( MSVC ) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /def:${CMAKE_CURRENT_SOURCE_DIR}/exp.def") endif () Здесь exp.def лежит в той же папке (CMAKE_CURRENT_SOURCE_DIR), что и CMakeLists.txt у dll. Поэтому здесь путь для линкера сделан относительно этой директории. Но вообще, странное желание. Обычно для подавления манглинга при экспорте используют обрамление extern "C" : Код (Text): extern "C" { __declspec(dllexport) int myfn(){return 0;}; };
Разве это поможет? У меня код на Си , а не на плюсах. По опциям попробую, спасибо. --- Сообщение объединено, 26 фев 2021 --- njeen, в общем, если в Си написать так Код (C): __declspec(dllexport) int WINAPI myfn(int a) { return 0; }; то будет имя с манглингом. А без WINAPI будет норм.
Ну ты понимаешь, что с WINAPI будет stdcall, а без WINAPI cdecl (мы же x86 обсуждаем)? Если тебя это устраивает, то окей, но у клиентов, которые будут вызывать твою библиотеку должны быть верные прототипы функций (с твоей конвенцией вызовов). --- Сообщение объединено, 26 фев 2021 --- У GCC есть параметр --kill-at для линкера, который у экспортируемых стдколл функций убирает постфикс @<N>, наверное у студии тоже что-то такое есть, можешь это передать, как дополнительный параметр для линкера.
Нет, не поможет, это только для c++. WINAPI означает stdcall соглашение - декорируется по-другому имя. Не указано - cdecl. Убирать просто так нельзя